1 场景说明
有些时候,我们希望将将异步函数放到vector当中,或者说是注册进vector当中,然后在某个地方遍历这个vector来实现对已经注册了的异步函数的调用。
Cargo.toml中需要的依赖
[dependencies]
tokio = { version = "1", features = ["full"] }
2 解决方案
因为rust需要知道如何分配内存,而不同的异步函数返回结果会不同,所以这里要用到Box和Pin。
2.1 无借用参数
当异步函数的输入参数重没有借用时,也就不涉及到生命周期的问题,这时可以参考下面这个例子来实现。
use std::{future::Future, pin::Pin};
type PinFutureObjWithoutLife<Output> = Pin<Box<dyn Future<Output = Output>>>;
type ItemWithoutLife = Box<dyn Fn(usize) -> PinFutureObjWithoutLife<()>>;
async fn collection_of_asyncs_without_ref() {
let vec: Vec<ItemWithoutLife> = vec![
Box::new(|num| Box::pin(func1_without_ref(num))),
Box::new(|num| Box::pin(func2_without_ref(num))),
Box::new(|num| Box::pin(func1_without_ref(num))),
Box::new(|num| Box::pin(func2_without_ref(num))),
];
for (idx, f) in vec.iter().enumerate() {
f(idx).await
}
}
async fn func1_without_ref(num: usize) -> ()
{
println!("func1_without_ref-{}", num);
}
async fn func2_without_ref(num: usize) -> ()
{
println!("func2_without_ref-{}", num);
}
#[tokio::main]
async fn main(){
collection_of_asyncs_without_ref().await;
}
2.2 有借用参数
当输入参数重带了借用参数的话,就有生命周期的问题了,rust需要我们指明生命周期,可以参考下面这个例子来实现。
use std::{future::Future, pin::Pin};
type PinFutureObjWithLife<'a, T> = Pin<Box<dyn Future<Output = T> + 'a>>;
type ItemWithLife = Box<dyn for<'a> Fn(&'a mut usize) -> PinFutureObjWithLife<'a, ()>>;
async fn collection_of_asyncs_with_ref() {
let mut vec = Vec::<ItemWithLife>::new();
vec.push(Box::new(|num| Box::pin(func1_with_ref(num))));
vec.push(Box::new(|num| Box::pin(func2_with_ref(num))));
vec.push(Box::new(|num| Box::pin(func1_with_ref(num))));
vec.push(Box::new(|num| Box::pin(func2_with_ref(num))));
for (mut idx, f) in vec.iter().enumerate() {
f(&mut idx).await
}
}
async fn func1_with_ref(num: &mut usize) -> ()
{
println!("func1_with_ref-{}", num);
}
async fn func2_with_ref(num: &mut usize) {
println!("func2_with_ref-{}", num);
}
#[tokio::main]
async fn main(){
collection_of_asyncs_with_ref().await;
}