How to fetch multiple with futures
💡 full source code is on github
foo.json
{
"id": "foo",
"type": "Cat",
"weight": 123.45,
"createdAt": "2022-09-01"
}
bar.json
{
"id": "bar",
"type": "Duck",
"weight": 42.2424,
"createdAt": "2022-08-01"
}
Cargo.toml
[package]
name = "fetch-multiple-futures"
version = "0.1.0"
edition = "2021"
[dependencies]
# Use No-std support https://serde.rs/no-std.html
serde = { version = "1.0", default-features = false, features = ["derive"] }
serde_json = "1.0"
# Use foe fetch, feature `json` for load json, `rustls-tls` for load via `TLS`.
reqwest = { version = "0.11", default-features = false, features = ["json", "rustls-tls"] }
# Use for handy return Result.
anyhow = "1.0.65"
# Use for async.
tokio = { version ="1.22", features = ["full"] }
futures = "0.3.25"
main.rs
use futures::future; use reqwest::Client; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] #[serde(rename_all = "camelCase")] struct AnimalData { id: String, weight: f32, created_at: String, } // Shared client for each call. async fn fetch_multiple_with_one_client_join_all(urls: &[&str]) -> anyhow::Result<Vec<AnimalData>> { // New shared client once. let client = Client::new(); // How to use join_all. let results = future::join_all(urls.iter().map(|&url| { // Use shared client. let client = &client; async move { let resp = client.get(url).send().await?; resp.json::<AnimalData>().await } })) .await; // Return flattened results, silent if error. Ok(results // We use into_iter so we get Vec<AnimalData> instead of Vec<&AnimalData> .into_iter() .flatten() .collect::<Vec<_>>()) } // Each client for each call. async fn fetch_multiple_with_each_client_join_all( urls: &[&str], ) -> anyhow::Result<Vec<AnimalData>> { // How to use join_all. let results = future::join_all(urls.iter().map(|&url| async move { // Fetch each url with new client. reqwest::get(url).await?.json::<AnimalData>().await })) .await; // Return flattened results, silent if error. Ok(results // We use into_iter so we get Vec<AnimalData> instead of Vec<&AnimalData> .into_iter() .flatten() .collect::<Vec<_>>()) } #[tokio::main] async fn main() { let urls = [ "https://raw.githubusercontent.com/gist-rs/book/main/examples/r4/30-fetch-multiple-futures/src/foo.json", "https://raw.githubusercontent.com/gist-rs/book/main/examples/r4/30-fetch-multiple-futures/src/bar.json" ]; let json = fetch_multiple_with_one_client_join_all(&urls).await; println!("{json:#?}"); let json = fetch_multiple_with_each_client_join_all(&urls).await; println!("{json:#?}"); }
🤷
reqwest
+TLS
is not runnable via Rust Playground so output is shown below.
Run
Ok(
[
AnimalData {
id: "foo",
weight: 123.45,
created_at: "2022-09-01",
},
AnimalData {
id: "bar",
weight: 42.2424,
created_at: "2022-08-01",
},
],
)
Ok(
[
AnimalData {
id: "foo",
weight: 123.45,
created_at: "2022-09-01",
},
AnimalData {
id: "bar",
weight: 42.2424,
created_at: "2022-08-01",
},
],
)