Как я могу выполнять параллельные асинхронные запросы HTTP GET с reqwest?
Пример асинхронности полезен, но, будучи новичком в Rust и Tokio, я изо всех сил пытаюсь понять, как выполнять N запросов одновременно, используя URL-адреса из вектора и создавая итератор HTML-ответа для каждого URL-адреса в виде строки.
Как это можно сделать?
2 ответа
По состоянию на 0,9:
extern crate futures; // 0.1.25
extern crate reqwest; // 0.9.5
extern crate tokio; // 0.1.11
use futures::{stream, Future, Stream};
use reqwest::async::Client;
type Result<T> = std::result::Result<T, Box<std::error::Error>>;
const N: usize = 1;
fn main() -> Result<()> {
let client = Client::new();
let urls = vec!["https://api.ipify.org", "https://api.ipify.org"];
let bodies = stream::iter_ok(urls)
.map(move |url| {
client
.get(url)
.send()
.and_then(|res| res.into_body().concat2().from_err())
})
.buffer_unordered(N);
let work = bodies
.for_each(|b| {
println!("Got {} bytes", b.len());
Ok(())
})
.map_err(|e| panic!("Error while processing: {}", e));
tokio::run(work);
Ok(())
}
stream::iter_ok(urls)
stream::iter_ok
Возьмите коллекцию строк и преобразуйте ее в Stream
,
.and_then(|res| res.into_body().concat2().from_err())
Stream::concat2
, Stream::from_err
Возьмите поток тела каждого ответа и соберите все в один большой кусок.
.buffer_unordered(N);
Stream::buffer_unordered
Преобразуйте поток фьючерсов в поток ценностей будущего, выполняя фьючерсы параллельно.
let work = bodies.for_each(|b| { println!("Got {} bytes", b.len()); Ok(()) });
Stream::for_each
Преобразуйте поток обратно в будущее.
Смотрите также:
Если возможно для вашей проблемы, я рекомендую использовать std async и rayon. Они оба уже созрели, и с ними действительно легко начать, учитывая асинхронный {/* код здесь */} границ области видимости в std. Вы также можете работать в / вместе с tokio с интеграцией функций https://docs.rs/async-std/1.10.0/async_std/#features