如何不使用OptionFuture在Option::and_then/map闭包中使用async/await
方案1:使用async块配合?运算符(最简洁)
直接把整个逻辑包在async块内,利用Rust中?运算符可以直接传播None的特性,代码量比你原来的OptionFuture写法少很多,逻辑也更直观:
let user_id = async { // 遇到None直接提前返回,和同步写法的行为完全一致 let session_token = Some("sessiontoken")?; let user = get_user(session_token).await?; Some(user.id) }.await;
这种写法不需要额外引入任何依赖,也不需要中间变量,你还可以在async块内任意使用Option的同步操作方法,只有需要await的步骤才涉及异步逻辑。相同逻辑也完全适用于Result类型,?运算符同样可以直接传播Err。
方案2:自定义异步扩展Trait(适合高频使用场景)
如果你的项目里经常需要做这类异步下的Option链式操作,可以自己封装一个异步扩展Trait,实现和同步and_then、map等对应的异步版本,一次封装到处使用:
首先定义扩展Trait:
use std::future::Future; trait AsyncOptionExt<T> { /// 异步版本的and_then,闭包返回一个Future,输出为Option fn and_then_async<U, F, Fut>(self, f: F) -> impl Future<Output = Option<U>> where F: FnOnce(T) -> Fut, Fut: Future<Output = Option<U>>; } impl<T> AsyncOptionExt<T> for Option<T> { async fn and_then_async<U, F, Fut>(self, f: F) -> Option<U> where F: FnOnce(T) -> Fut, Fut: Future<Output = Option<U>>, { match self { Some(v) => f(v).await, None => None, } } }
使用的时候和同步and_then的写法几乎没有区别:
let user_id = Some("sessiontoken") .and_then_async(|session_token| async move { get_user(session_token).await.map(|user| user.id) }) .await;
同理你也可以按照相同的模式实现map_async、ok_or_async等其他你需要的异步操作方法,完全匹配同步Option的使用体验。
内容的提问来源于stack exchange,提问作者Filippo Orrù
相关产品推荐
相关产品推荐

