在我的RSS reader project中,我想异步读取我的RSS feed。当前,由于this code block
可以同步读取它们self.feeds = self
.feeds
.iter()
.map(|f| f.read(&self.settings))
.collect::<Vec<Feed>>();
我想使该代码异步,因为它将使我能够更好地处理不良的Web服务器响应。
我了解我可以使用Stream
通过Vec
从stream::from_iter(...)
创建的self.feeds = stream::from_iter(self.feeds.iter())
.map(|f| f.read(&self.settings))
// ???
.collect::<Vec<Feed>>()
}
,它将代码转换为类似的内容
Vec
但是,我有两个问题
task::spawn
(这是一个同步结构)中?className={mystyle}
,但似乎不起作用... 答案 0 :(得分:0)
如何执行该流?我当时在考虑使用
task::spawn
,但似乎不起作用
在async/await
世界中,异步代码是由执行者执行的,该执行者不是标准库的一部分,而是由诸如tokio
之类的第三方包装箱提供的。 task::spawn
仅调度async fn
的一个实例运行,而不实际运行它。
如何将结果加入vec(这是一个同步结构)
您的RSS读者的面包和黄油似乎是f.read
。它应该变成一个异步函数。然后将提要的向量映射到期货的向量中,需要对其进行轮询才能完成。
futures
板条箱有futures::stream::futures_unordered::FuturesUnordered
可以帮助您完成此操作。 FuturesUnordered
本身实现了Stream
特征。然后将此流收集到结果向量中,并await
完成,如下所示:
//# tokio = { version = "0.2.4", features = ["full"] }
//# futures = "0.3.1"
use tokio::time::delay_for;
use futures::stream::StreamExt;
use futures::stream::futures_unordered::FuturesUnordered;
use std::error::Error;
use std::time::{Duration, Instant};
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let start = Instant::now();
let feeds = (0..10).collect::<Vec<_>>();
let res = read_feeds(feeds).await;
dbg!(res);
dbg!(start.elapsed());
Ok(())
}
async fn read_feeds(feeds: Vec<u32>) -> Vec<u32> {
feeds.iter()
.map(read_feed)
.collect::<FuturesUnordered<_>>()
.collect::<Vec<_>>()
.await
}
async fn read_feed(feed: &u32) -> u32 {
delay_for(Duration::from_millis(500)).await;
feed * 2
}
delay_for
用于模拟潜在的昂贵操作。这也有助于证明这些读取确实是并发发生的,而没有任何与线程相关的显式逻辑。
这里有一个细微差别。与同步同步不同,读取rss feed的结果不再是feeds本身的顺序,无论哪个返回值都位于最前面。您需要以某种方式处理。