use futures::future; // 0.3.4
use reqwest::Client; // 0.10.1
use tokio; // 0.2.11
#[tokio::main]
async fn main() {
let client = Client::new();
let urls = vec!["https://api.ipify.org"; 2];
let bodies = future::join_all(urls.into_iter().map(|url| {
let client = &client;
async move {
let resp = client.get(url).send().await?;
resp.bytes().await
}
}))
.await;
for b in bodies {
match b {
Ok(b) => println!("Got {} bytes", b.len()),
Err(e) => eprintln!("Got an error: {}", e),
}
}
}
2条答案
按热度按时间zu0ti5jz1#
并发请求
自2014年11月04日起:
stream::iter
取一个字符串集合并将其转换为
Stream
。StreamExt::map
对流中的每个元素运行异步函数,并将元素转换为新类型。
获取对
Client
的显式引用,并将该引用(不是原始的Client
)移动到匿名异步块中。使用
Client
的连接池启动异步GET请求并等待该请求。请求并等待响应的字节数。
StreamExt::buffer_unordered
将一个期货流转换为这些期货值的流,同时执行这些期货。
StreamExt::for_each
将流转换回单个future,打印出沿着接收到的数据量,然后等待future完成。
另见:
then
,and_then
andor_else
in Rust futures?无绑定执行
如果愿意,还可以将迭代器转换为future的迭代器,并使用
future::join_all
:我建议使用第一个示例,因为您通常希望限制并发性,
buffer
和buffer_unordered
有助于实现这一点。并行请求
并发请求通常就足够了,但是有时候你需要并行请求,在这种情况下,你需要生成一个任务。
主要区别是:
tokio::spawn
来执行独立的 * task * 工作。reqwest::Client
,克隆一个共享客户端来使用连接池。另见:
5gfr0r5j2#
如果可能的话,我推荐使用std async和rayon。它们现在都很成熟,并且在std中的async{/* code here */}范围界限的情况下非常容易上手。您也可以使用时雄的特性集成https://docs.rs/async-std/1.10.0/async_std/#features