我如何从 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::Future
而 into_actor
期望 futures01::future::Future
.
在调用 .into_actor
之前调用 future 的 .compat()
解决了这个问题。
有关转换期货的更多详细信息,请参阅 this post。
我有一个异步特征方法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::Future
而 into_actor
期望 futures01::future::Future
.
在调用 .into_actor
之前调用 future 的 .compat()
解决了这个问题。
有关转换期货的更多详细信息,请参阅 this post。