3

我想运行类似下面的代码:

async fn get_user(s: &str) -> Option<User> { /* ... */ }

let user_id = Some("sessiontoken").and_then(|session_token| {
    get_user(session_token)
        .await // <- error
        .map(|user| user.id)
});

但它不起作用,因为 await 只能在异步块或函数中使用。另一方面,如果我使用异步块,则闭包将返回impl Future<Output = Option<_>>这是不允许的,因为Option::and_then只允许Option作为返回类型。

我知道的唯一选择是使用OptionFuture,创建一个中间变量,.map而不是.and_then.

use futures::future::OptionFuture;

let user: OptionFuture<_> = Some("sessiontoken")
    .map(|session_token| {
        get_user(session_token)
    })
    .into();
let user_id = user.await.flatten().map(|user| user.id);

但这确实很麻烦,并且使我无法使用许多可以对 Options、Results 或类似内容进行操作的函数,例如Option::and_then.

没有更好的办法吗?

4

2 回答 2

0

我相信惯用的方法是简单地使用match

let user_id = match session_token {
    Some(session_token) => get_user("sessiontoken").await.map(|user| user.id),
    None => None,
};
于 2021-11-04T19:47:58.920 回答
-1

假设您正在使用tokio,您可以使用block_on,例如:

use tokio::runtime::Runtime;
use futures::future::OptionFuture;


// Create the runtime
let rt = Runtime::new().unwrap();


let user_id = Some("sessiontoken").and_then(|session_token| {
    rt.block_on(get_user(session_token)).map(|user| user.id)
});
于 2021-11-04T20:54:36.307 回答