Join
join 操作は、一連の future がすべて準備できるまで待機し、それらの結果のコレクションを返します。これは、JavaScript の Promise.all や Python の asyncio.gather に似ています。
// 著作権 2024 Google LLC // SPDX-License-Identifier: Apache-2.0 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 にコピーし、そこから実行してください。
-
型が異なる複数の future に対しては
std::future::join!を使えますが、コンパイル時に future の数が分かっている必要があります。これは現在はfuturesクレートにあり、近いうちにstd::futureで安定化される予定です。 -
joinのリスクは、future の 1 つが決して解決しない可能性があることです。そうなると、プログラムは停止したままになります。 -
たとえば、HTTP サービスへのすべてのリクエストとデータベースクエリをまとめて join するために、
join_allとjoin!を組み合わせることもできます。futures::join!を使って、future にtokio::time::sleepを追加してみてください。これはタイムアウトではありません(タイムアウトにはselect!が必要で、次の章で説明します)が、join!を示しています。