这个 Future 的实现失败了什么?

What fails in this Future implementation?

虽然代码可以编译,但我不明白为什么直接使用 await 会卡在第一个请求中。 为什么我需要使用方法 execute_requests 而不是在 Future 实现上调用它?

// ...

async fn send(url: &str) {
    println!("Sending to URL {}", url);
    // Simulate the sending process
    sleep(Duration::from_millis(500)).await;
}

type Request = Pin<Box<dyn Future<Output = ()>>>;

struct Proxy;

impl Proxy {
    async fn execute_requests(&self) {
        let request_1 = async {
            send("url 1").await;
        };
        let request_2 = async {
            send("url 2").await;
        };

        let mut requests: Vec<Request> = vec![];
        requests.push(Box::pin(request_2));
        requests.push(Box::pin(request_1));

        while let Some(request) = requests.pop() {
            request.await;
        }
    }
}

impl Future for Proxy {
    type Output = ();

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let mut queue_process = Box::pin(self.execute_requests());
        queue_process.as_mut().poll(cx)
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let proxy = Proxy;
    // Executes both requests
    // Ok(proxy.execute_requests().await)
    // FIXME: Timeouts on the first request
    Ok(proxy.await)
}

Rust Playground

已编辑:execute_requests 是一种简化:它需要访问 self 才能获取请求和其他内容。

每次轮询时,您都会创建一个新的 execute_requests() 未来并轮询一次。它永远不会前进到下一次投票 - 下次调用您的 poll() 时,将创建一个新的未来并将被投票一次,依此类推。

相反,您应该将 execute_requests() 未来存储在 Proxy 中,并轮询相同的未来:

struct Proxy(Pin<Box<dyn Future<Output = ()>>>);

impl Proxy {
    fn new() -> Self {
        Self(Box::pin(Self::execute_requests()))
    }
    
    async fn execute_requests() {
        let request_1 = async {
            send("url 1").await;
        };
        let request_2 = async {
            send("url 2").await;
        };

        let mut requests: Vec<Request> = vec![];
        requests.push(Box::pin(request_2));
        requests.push(Box::pin(request_1));

        while let Some(request) = requests.pop() {
            request.await;
        }
    }
}

impl Future for Proxy {
    type Output = ();

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        self.0.as_mut().poll(cx)
    }
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let proxy = Proxy::new();
    // Executes both requests
    // Ok(proxy.execute_requests().await)
    // FIXME: Timeouts on the first request
    Ok(proxy.await)
}

Playground.