rust - 是否可以为异步函数创建类型别名?
问题描述
我想创建一个类型别名来提升函数的闭包,而用户不必考虑函数的参数和返回签名。这将翻译这段代码:
async fn some_func(s: &mut Context<Props>) -> VNode {
// some function body...
}
进入这段代码:
static SomeFunc: FC<Props> = |ctx| async {
// some function body
};
在 JavaScript 中,这将使用 const 闭包函数定义而不是常规函数简写。
对于常规功能,这很好用:
type FC<T: Props> = fn(&mut Context<T>) -> Vnode;
然后,静态闭包被提升为函数指针。
但是,impl Future
不能在类型别名中使用(甚至不能在 1.51 nightly 中使用),而且我也不能在类型别名中使用通用特征边界。我不知道这是否可能,但我很好奇类型别名是否有办法为异步 fns 工作。
为什么?
我正在设计的 API 将函数作为输入(不是结构或特征对象),我想让它易于使用。
解决方案
您不能直接执行此操作,因为每个 async fn 都有不同的返回类型,即使未来计算为相同的类型。这是因为每个 async fn 都有它自己Future
返回的唯一类型。
为此,您必须使用特征对象 ( dyn Fn
) 而不是函数指针 ( fn()
) 作为类型。您正在寻找的类型是
use futures::future::BoxFuture;
type FC<T> = Box<dyn Send + Sync + for<'a> Fn(&'a mut Context<T>) -> BoxFuture<'a, Vnode>>;
上述类型将作为返回 a 的函数Future
,但需要一个转换步骤才能从普通的 async fn 转换为上述类型的函数。
可以按如下方式执行此转换:
Box::new(|context| Box::pin(my_async_fn(context)))
它也可以使用期货箱来编写。在某些情况下,使用的版本.boxed()
将有助于类型检查器并避免该Box::pin
版本可能给出的一些错误。
use futures::future::FutureExt;
Box::new(|context| my_async_fn(context).boxed())
由于我们在这种情况下使用的特定类型别名涉及生命周期,因此无法为上述定义方便的转换。也就是说,当参数不是引用时,您可以这样做:
use futures::future::BoxFuture;
type AsyncFnPtr = Box<dyn Send + Sync + Fn(SomeArg) -> BoxFuture<'static, RetValue>>;
fn convert<F, Fut>(func: F) -> AsyncFnPtr
where
F: Send + Sync + 'static,
F: Fn(SomeArg) -> Fut,
Fut: Send + 'static,
Fut: Future<Output = RetValue>,
{
Box::new(|context| Box::pin(func(context)))
}
其他资源:
推荐阅读
- c# - 如何在 Enumerable.Zip 扩展方法 c# 中删除重复项?
- angular - 角度库中服务的属性和方法
- html - iframe 的替代品
- javascript - TypeError:this.props.messages.map 不是函数
- python - 如何在前缀上安装 numpy?
- javascript - 通过 html.actionlink 传递 javascript 值
- java - 尝试创建视图时带有 afterburner.fx 的 NullPointer
- excel - 使用powerquery从excel中提取数据
- kubernetes - 有没有一种简单的方法可以从副本集创建 Kubernetes 部署?
- javascript - try/catch 块上未处理的 Promise 拒绝