Say we have n servers, and we only need k < n responses .
I understand futures::join_all can be used to wait for all n futures, but I want my program finish waiting after k responses.
Is there something similar to join_all that I can use to wait for the first k responses?
To prevent multiple awaits, chaining futures in . then(), you can simply use Future. wait([]) that returns an array of results you were waiting for. If any of those Futures within that array fails, Future.
async transforms a block of code into a state machine that implements a trait called Future . Whereas calling a blocking function in a synchronous method would block the whole thread, blocked Future s will yield control of the thread, allowing other Future s to run. The value returned by async fn is a Future .
The await operator is used to wait for a Promise . It can only be used inside an async function within regular JavaScript code; however it can be used on its own with JavaScript modules.
Sometimes you don't want to turn the function into a Future or mark it async, so the other way to handle a Future is by using the . then function. It takes in a function that will be called with the value type of your Future. It's similar to a Promise in JavaScript without the resolve, reject explicitness.
You can use streams (async iterators) for this. You can use FuturesUnordered
as an unordered collection of futures, which can be used as a stream where you get each future's result in the order they complete. Then you can combine this with .take(n)
to only take the first n
items of the stream, and then .collect::<Vec<_>>()
to wait for the stream to finish and collect the results in a Vec
:
use futures::prelude::*;
use futures::stream::FuturesUnordered;
let futures = vec![
// assume `f(n, t)` = sleep for `t` millis, then return `n`
f(1, 1000),
f(2, 10),
f(3, 105),
f(4, 40),
f(5, 70),
f(6, 270),
];
// create unordered collection of futures
let futures = futures.into_iter().collect::<FuturesUnordered<_>>();
// use collection as a stream, await only first 4 futures to complete
let first_4 = futures.take(4).collect::<Vec<_>>().await;
// note: any remaining futures will be cancelled automatically when the
// stream is consumed
// check with expected result, based on the order of completion
assert_eq!(first_4, vec![2, 4, 5, 3]);
Playground example
Edit: If you want to also get the index of completed the future, you can use this:
// create unordered collection of futures with indices
let futures = futures
.into_iter()
.enumerate()
.map(|(i, fut)| fut.map(move |res| (i, res)))
.collect::<FuturesUnordered<_>>()
Playground example
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With