1 个不稳定版本

0.1.0 2024年1月13日

#882 in 异步

MIT/Apache

67KB
2K SLoC

Async Iter

此库提供了Rust的Iterator特性和异步版本的实用工具。

快速入门

添加到依赖项

将async-iter添加到依赖项

cargo add asynciter

实用工具入口

然后,导入基本特性

use asynciter::{
    // This offers standard api, just like the `std::iter::Iterator`
    AsyncIterator,
    // use `.aiter()` to convert a synchronous iterator
    // into an asynchronous one
    ToAsyncIterator,
    // use `.into_aiter()` to convert a synchronous iterable object
    // into an asynchronous iterator
    IntoAsyncIterator,
}

API调用栈

所有API名称和限制都与std相同。您只需要将.iter().into_iter()更改为.aiter().into_aiter()

assert_eq!(
    ["Hello%", "World%", "!"]
        .into_aiter()
        .map(|s| s.to_ascii_lowercase())
        .intersperse(" ".into())
        .flat_map(|s| s.chars().filter(|s| s != &'%').collect::<Vec<_>>())
        .collect::<String>()
        .await,
    "hello world !"
);

异步替代方案

如果您想在迭代器中使用异步函数,以a为前缀的api将接受返回Future的函数,其工作方式与同步函数相同

async fn do_async(val: i32) -> String {
    format!("Async! {val}")
}

(0..=10)
    .aiter()
    // `amap` accepts `FnMut(Item) -> Future<Output>`
    .amap(do_async)
    // `afor_each` accepts `FnMut(Item) -> Future<Output = ()>`
    .afor_each(|s| async move {
        println!("{s}");
    })
    .await;

等待的异步迭代器

如果您有一个产生Future的迭代器,请使用.awaited()将它们转换为AsyncIterator

// impl Iterator<Output: Future<Output = i32>>
let sync_it = (0..10).map(|s| async move { s + 1 });
// impl AsyncIterator<Output = i32>
let async_it = sync_it.aiter().awaited();

内部实现

所有内部实现都可以在asynciter::iterimpl模块中找到,并公开导出,但不建议直接使用。

注意

对于接受FnXXX(&Self::Item) -> Future的api,还有一个额外的限制。由于Future将在函数调用之后使用,引用可能会超出函数调用的生命周期,导致编译器失败。为了保持代码的安全性,引用必须在Future之外进行处理和释放。

例如,以下代码将无法通过编译器检查

(0..10)
    .aiter()
    .afilter(
        |s| // Here we accept the reference
        async move {
            *s < 5 // And we use it here.
            // The reference will live longer than the function,
            // which is not safe.
        }
    )

相反,我们必须使用以下解决方案

(0..10)
    .map(|s| s.to_string())
    .aiter()
    .afilter(|s| {
        let s = s.clone(); // Here we save the reference
                           // by cloning the value
        async move {
            // do something
            false
        }
    })
    .for_each(|_| {}).await;

许可证

本项目受MIT许可证Apache V2.0许可证许可。

无运行时依赖项