我如何从 actix 处理程序中调用固定的未来?

How can I call a Pinned future from an actix handler?

我有一个异步特征方法returns一个标准的未来:

Pin<Box<dyn Future<Output = Result<Vec<ResultType>, Box<(dyn Error + 'static)>>> + Send>>

ResultType 是特征的关联类型,即 Sync + Send.

请注意,此类型不是取消固定

我想从 actix 处理程序调用它,然后对结果做一些处理。

例如:

impl StreamHandler<ws::Message, ws::ProtocolError> for MyActor {
    fn handle(&mut self, msg: ws::Message) {
        let fut = get_future();
        let actor_fut = fut
            .into_actor(&self)
            .map(|r, _actor, ctx| {
                ctx.text(r.map(|| ...))
            });

        ctx.spawn(actor_fut);
    }
}

这失败了,因为 into_actor 取得了未来的所有权,这是 Pin 不允许的。清理后的错误消息如下所示:

error[E0599]: no method named `into_actor` found for type `Pin<Box<dyn Future<Output = Result<Vec<ResultType>, Box<dyn Error>>> + Send>>` in the current scope
   --> src/app_socket.rs:194:26
    |
194 |                         .into_actor(&self)
    |                          ^^^^^^^^^^ method not found in `Pin<Box<dyn Future<Output = Result<Vec<ResultType>, Box<dyn Error>>> + Send>>`
    |
    = note: the method `into_actor` exists but the following trait bounds were not satisfied:
            `&dyn Future<Output = Result<std::vec::Vec<ResultType>, std::boxed::Box<dyn std::error::Error>>> + Send : WrapFuture<_>`
            `&dyn Future<Output = Result<std::vec::Vec<ResultType>, std::boxed::Box<dyn std::error::Error>>> + Send : WrapStream<_>`
            `&mut dyn Future<Output = Result<std::vec::Vec<ResultType>, std::boxed::Box<dyn std::error::Error>>> + Send : WrapFuture<_>`
            `&mut dyn Future<Output = Result<std::vec::Vec<ResultType>, std::boxed::Box<dyn std::error::Error>>> + Send : WrapStream<_>`
            `&mut Pin<std::boxed::Box<dyn Future<Output = Result<std::vec::Vec<ResultType>, std::boxed::Box<dyn std::error::Error>>> + Send>> : WrapFuture<_>`
            `&mut Pin<std::boxed::Box<dyn Future<Output = Result<std::vec::Vec<ResultType>, std::boxed::Box<dyn std::error::Error>>> + Send>> : WrapStream<_>`
            `&Pin<std::boxed::Box<dyn Future<Output = Result<std::vec::Vec<ResultType>, std::boxed::Box<dyn std::error::Error>>> + Send>> : WrapFuture<_>`
            `&Pin<std::boxed::Box<dyn Future<Output = Result<std::vec::Vec<ResultType>, std::boxed::Box<dyn std::error::Error>>> + Send>> : WrapStream<_>`
            `dyn Future<Output = Result<std::vec::Vec<ResultType>, std::boxed::Box<dyn std::error::Error>>> + Send : WrapFuture<_>`
            `dyn Future<Output = Result<std::vec::Vec<ResultType>, std::boxed::Box<dyn std::error::Error>>> + Send : WrapStream<_>`
            `Pin<std::boxed::Box<dyn Future<Output = Result<std::vec::Vec<ResultType>, std::boxed::Box<dyn std::error::Error>>> + Send>> : WrapFuture<_>`
            `Pin<std::boxed::Box<dyn Future<Output = Result<std::vec::Vec<ResultType>, std::boxed::Box<dyn std::error::Error>>> + Send>> : WrapStream<_>`

我该怎么做?

实际问题不是 future 被固定了,而是它实现了错误的 future trait。

This section on Pinning 解释说 poll 是为 Pin<ref T: Future> 实现的。

因此,into_actor 签名 self: impl Future -> WrapFuture<_> 没问题。问题是 async 方法返回了一个未来的实现 std::future::Futureinto_actor 期望 futures01::future::Future.

在调用 .into_actor 之前调用 future 的 .compat() 解决了这个问题。

有关转换期货的更多详细信息,请参阅 this post