I can asynchronously resolve a bunch of promises with Promise.all(array)
. However .then()
will run only after all those promises have been resolved. How I can perform actions as the promises get resolved?
For example, I want to load all paragraphs from an article asynchronously using Promise.all()
- This way the network requests all fire at once. If paragraph 1 is done loading, I want it to render to the page - but only if it is done loading before paragraph 2, then I want paragraph 2 to load. If paragraph 3 is done loading and 2 is not, I want 3 to wait for 2 before rendering to the page. And so on.
I tried something like this but I don't know what to do next:
var getStuff = function(number, time){
return new Promise(function(resolve, reject){
window.setTimeout(function(){resolve(`${number} - Done.`)}, time);
});
};
Promise.all([ getStuff(1, 200),
getStuff(2, 100),
getStuff(3, 250),
getStuff(4, 200),
getStuff(5, 300),
getStuff(6, 250),
getStuff(7, 5000)])
.then(function(data){
console.log(data);
});
How can I get the console log of the data to happen one after another - without resolving each promise with a then()
before making the next request? Is there a better way to do this?
If an empty iterable is passed, then the promise returned by this method is fulfilled synchronously. The fulfilled value is an empty array.
Here, Promise. all() method is the order of the maintained promises. The first promise in the array will get resolved to the first element of the output array, the second promise will be a second element in the output array and so on.
people seems to be an array of paths you want to fetch, you can map the array to a list of promises, then use Promise. all() to wait for them all to resolve: return c. scraper.
Promise. any() takes an iterable of Promise objects. It returns a single promise that fulfills as soon as any of the promises in the iterable fulfills, with the value of the fulfilled promise.
You cannot achieve this order using Promise.all
because the promise returned from Promise.all
waits for all promises from the provided array to resolve concurrently (as opposed to sequentially) before it itself resolves.
Instead, you can individually create the promises and fire of their requests concurrently:
// create promises and make concurrent requests
const s1 = getStuff(1, 200);
const s2 = getStuff(2, 100);
const s3 = getStuff(3, 250);
// ...
Then create a reaction chain on how to process them (stuff1 before stuff2, stuff2 before stuff3, etc.)
// create a chain of reaction order to the results of parallel promises
s1
.then(console.log) // s1 resolved: log result
.then(() => s2) // chain s2
.then(console.log) // s2 resolved: log result
.then(() => s3) // chain s3
// ...
.then(() => { // chain another function at at the end for when all promises resolved
// all promises resolved (all data was logged)
}
To react to promise results in the same order the promises were created, you can change your getStuff
function to dynamically chain the reactions using Array.prototype.reduce
:
var times = [200, 100, 250, 200, 300, 250, 5000];
var getStuff = function(time, index) { // swap the order of arguments so number is the index passed in from Array.map
return new Promise((resolve, reject) => {
window.setTimeout(() => {
resolve(`${index + 1} - Done.`); // use index + 1 because indexes start at 0
}, time);
});
};
times
// map each time to a promise (and number to the index of that time + 1) and fire of a request
.map(getStuff)
// dynamically build a reaction chain for the results of promises
.reduce((chain, promise) => {
return chain
.then(() => promise)
.then(console.log);
}, Promise.resolve())
.then(() => {
// all promises resolved (all data was logged in order)
});
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