Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use async/await inside closure of `Option::and_then` or `Option::map` without using OptionFuture?

I would like to run something like the following code:

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)
});

But it doesn't work because await can only be used inside async blocks or functions. If, on the other hand, I use an async block, the closure would return impl Future<Output = Option<_>> which is not allowed because Option::and_then only allows Option as a return type.

The only alternative I know would be to use OptionFuture, create an intermediate variable and .map instead of .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);

But this is really cumbersome and prevents me from using many functions that would operate on Options, Results or similar, such as Option::and_then.

Is there no better way?

like image 255
Filippo Orrù Avatar asked Dec 04 '25 21:12

Filippo Orrù


1 Answers

I believe the idiomatic way would be to simply use match:

let user_id = match session_token {
    Some(session_token) => get_user("sessiontoken").await.map(|user| user.id),
    None => None,
};
like image 103
kmdreko Avatar answered Dec 07 '25 15:12

kmdreko



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!