Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perform actions as promises get fulfilled using Promise.all()

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?

like image 494
hackrnaut Avatar asked Sep 27 '16 15:09

hackrnaut


People also ask

What is the fulfilled value of promise all ()?

If an empty iterable is passed, then the promise returned by this method is fulfilled synchronously. The fulfilled value is an empty array.

Does promise all resolve promises in order?

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.

How do you use promise all inside then chain?

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.

What is the use of promise Any ()?

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.


1 Answers

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)
  });
like image 154
nem035 Avatar answered Oct 14 '22 10:10

nem035