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);
}
This slide should take about 4 minutes.

Скопіюйте цей приклад у ваш підготовлений src/main.rs і запустіть його звідти.

  • Для кількох ф’ючерсів непересічних типів ви можете використовувати std::future::join!, але ви повинні знати, скільки ф’ючерсів у вас буде під час компіляції. Наразі це в коейті futures, незабаром буде стабілізовано в std::future.

  • Ризик join полягає в тому, що один із ф'ючерсів може ніколи не вирішитися, це призведе до зависання вашої програми.

  • Ви також можете поєднати join_all з join!, наприклад, щоб об’єднати всі запити до служби http, а також запит до бази даних. Спробуйте додати tokio::time::sleep до ф'ючерсу, використовуючи futures::join!. Це не тайм-аут (який вимагає select!, пояснюється в наступному розділі), але демонструє join!.