我们有有限数量的 vec(长度未知)的期货。每个 future vec 都有不同的结果类型,因此我们不能只是将它们展平。我们想做一些类似 try_join 的事情,等待一个返回错误,或者全部返回成功。
执行此连接的位置已经在异步上下文中。加入的 future 必须同时处于活动状态,因此我们不能一次尝试加入一个 vec。
在 Rust 异步中实现这个的好方法是什么?
您可以添加一个中间映射步骤,将每个
Future
的结果转换为一致的类型,然后再将它们传递给 try_join_all
:
use futures::future::FutureExt;
use std::future::Future;
use std::pin::Pin;
#[tokio::main]
async fn main() {
let int_futures: Vec<Pin<Box<dyn Future<Output = Result<String, u8>> + Send>>> = vec![
async { Ok("ok".to_owned()) }.boxed(),
async { Err(0) }.boxed(),
];
let bool_futures: Vec<Pin<Box<dyn Future<Output = Result<String, bool>> + Send>>> = vec![
async { Ok("ok".to_owned()) }.boxed(),
async { Err(false) }.boxed(),
];
#[derive(Debug)]
#[allow(unused)]
enum EitherError {
Int(u8),
Bool(bool),
}
let result: Result<Vec<String>, EitherError> = futures_util::future::try_join_all(
int_futures
.into_iter()
.map(|f| -> Pin<Box<dyn Future<Output = _>>> {
f.map(|r| r.map_err(EitherError::Int)).boxed()
})
.chain(
bool_futures
.into_iter()
.map(|f| -> Pin<Box<dyn Future<Output = _>>> {
f.map(|r| r.map_err(EitherError::Bool)).boxed()
}),
),
)
.await;
// e.g. Err(Int(0))
println!("{result:?}");
}