Join
Операція об’єднання очікує, поки весь набір ф’ючерсів буде готовий, і повертає колекцію їхніх результатів. Це схоже на Promise.all у JavaScript або asyncio.gather у Python.
use anyhow::Result;
use futures::future;
use reqwest;
use std::collections::HashMap;
async fn size_of_page(url: &str) -> Result<usize> {
let resp = reqwest::get(url).await?;
Ok(resp.text().await?.len())
}
#[tokio::main]
async fn main() {
let urls: [&str; 4] = [
"https://google.com",
"https://httpbin.org/ip",
"https://play.rust-lang.org/",
"BAD_URL",
];
let futures_iter = urls.into_iter().map(size_of_page);
let results = future::join_all(futures_iter).await;
let page_sizes_dict: HashMap<&str, Result<usize>> =
urls.into_iter().zip(results.into_iter()).collect();
println!("{page_sizes_dict:?}");
}
Скопіюйте цей приклад у ваш підготовлений src/main.rs і запустіть його звідти.
-
Для кількох ф’ючерсів непересічних типів ви можете використовувати
std::future::join!, але ви повинні знати, скільки ф’ючерсів у вас буде під час компіляції. Наразі це в коейтіfutures, незабаром буде стабілізовано вstd::future. -
Ризик
joinполягає в тому, що один із ф’ючерсів може ніколи не вирішитися, це призведе до зависання вашої програми. -
Ви також можете поєднати
join_allзjoin!, наприклад, щоб об’єднати всі запити до служби http, а також запит до бази даних. Спробуйте додатиtokio::time::sleepдо ф’ючерсу, використовуючиfutures::join!. Це не тайм-аут (який вимагаєselect!, пояснюється в наступному розділі), але демонструєjoin!.