如何从包含未来的结果中创建未来?
How to create a Future from a Result containing a 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
函数后执行此操作,所以也许这是我的第一个错误。
如果 result
是 Ok
你可以简单地 return 内在的未来。但是,如果它是 Err
,那么你必须构建一个新的未来解析为 Result<U, E>::Err(e)
。这意味着您不能 return 通用 Future
因为两个 match
臂 return 是两种不同的类型。你必须 return 一个特征对象:
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) })
}
}
可能人们通常想要的是立即处理 Err
案例,而不是等到 .await
ed 之后再处理,这样就可以解释为什么这样的功能还不存在.但是,如果您确实需要它,使用 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
(传递给函数的一层和从未来返回的一层)展平。
是否可以(合乎逻辑?)将包含未来的结果转换为解析为结果的未来?
以下功能有点破损,但希望能使我想要实现的目标更加清晰:
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
函数后执行此操作,所以也许这是我的第一个错误。
如果 result
是 Ok
你可以简单地 return 内在的未来。但是,如果它是 Err
,那么你必须构建一个新的未来解析为 Result<U, E>::Err(e)
。这意味着您不能 return 通用 Future
因为两个 match
臂 return 是两种不同的类型。你必须 return 一个特征对象:
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) })
}
}
可能人们通常想要的是立即处理 Err
案例,而不是等到 .await
ed 之后再处理,这样就可以解释为什么这样的功能还不存在.但是,如果您确实需要它,使用 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
(传递给函数的一层和从未来返回的一层)展平。