如何从包含Future的结果创建Future



是否可以(逻辑?(将包含未来的结果转换为解析为结果的未来?

以下功能有点坏,但希望能让我试图实现的目标更加清晰:

use std::future::Future;
fn transpose<T,U,E>(result: Result<T,E>) -> impl Future<Output = Result<U, E>>
where T: Future<Output = Result<U,E>> /* not sure if this is the correct trait bound */ {
match result {
Ok(inner) => /* a future that eventually resolves to a Result<U, E> */
Err(error) => /* a future that immediately resolves to a Result<U, E>::Err(error) */
}
}

为了提供一些上下文:在从传递给Result::map的闭包中调用async函数后,我发现自己需要这样做,所以这可能是我的第一个错误。

可能人们通常想要的是立即处理Err的情况,而不是等到将来是.await,所以这可能解释了为什么这样的函数还不存在。然而,如果您确实需要它,那么使用async.await:编写非常简单

fn transpose_flatten<T, U, E>(result: Result<T, E>) -> impl Future<Output = Result<U, E>>
where
T: Future<Output = Result<U, E>>,
{
async {                          // when polled,
match result {
Ok(good) => good.await,  // defer to the inner Future if it exists
Err(bad) => Err(bad),    // otherwise return the error immediately
}
}
}

或者使用async fn的事情是一样的(这并不总是完全一样的,但在这种情况下似乎是一样的(:

async fn transpose_flatten<T, U, E>(result: Result<T, E>) -> Result<U, E>
where
T: Future<Output = Result<U, E>>,
{
match result {
Ok(good) => good.await,
Err(bad) => Err(bad),
}
}

由于Err值是从封闭的async块或函数返回的,因此可以使用?语法使其更短:

async fn transpose_flatten<T, U, E>(result: Result<T, E>) -> Result<U, E>
where
T: Future<Output = Result<U, E>>,
{
result?.await
}

我之所以调用这个函数transpose_flatten,是因为对我来说,transpose听起来应该使用Result<Future<Output = U>, _>。此函数使Result的两层变平(传递给函数的一层和将来返回的一层(。

如果resultOk,您可以简单地返回内部未来。但是,如果它是Err,则必须构造一个新的将来解析为Result<U, E>::Err(e)。这意味着您不能返回泛型Future,因为两个match臂返回两个不同的类型。你必须返回一个特征对象:

fn transpose<T, E: 'static, U: 'static>(result: Result<T, E>) -> Box<dyn Future<Output = Result<U, E>>>
where T: Future<Output = Result<U, E>> + 'static {
match result {
Ok(inner) => Box::new(inner),
Err(error) => Box::new(async { Err(error) })
}
}

最新更新