Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Waiting for all promises called in a loop to finish

I'm using the axios promise library, but my question applies more generally I think. Right now I'm looping over some data and making a single REST call per iteration.
As each call completes I need to add the return value to an object. At a high level, it looks like this:

var mainObject = {};  myArrayOfData.forEach(function(singleElement){   myUrl = singleElement.webAddress;   axios.get(myUrl)   .then(function(response) {     mainObject[response.identifier] = response.value;    }); });  console.log(convertToStringValue(mainObject)); 

What's happening of course is when I call console.log the mainObject doesn't have any data in it yet, since axios is still reaching out. What's a good way of dealing with this situation?

Axios does have an all method along with a sister spread one, but they appear to be of use if you know ahead of time how many calls you'll be making, whereas in my case I don't know how many loop iterations there will be.

like image 500
jkj2000 Avatar asked May 13 '16 15:05

jkj2000


People also ask

How do you call a promise in a for loop?

To use Javascript promises in a for loop, use async / await . This waits for each promiseAction to complete before continuing to the next iteration in the loop. In this guide, you learn how async/await works and how it solves the problem of using promises in for loops.

How Use promise all with async await?

async and await Inside an async function, you can use the await keyword before a call to a function that returns a promise. This makes the code wait at that point until the promise is settled, at which point the fulfilled value of the promise is treated as a return value, or the rejected value is thrown.

How do you make a promise to wait?

The keyword await is used to wait for a Promise. It can only be used inside an async function. This keyword makes JavaScript wait until that promise settles and returns its result.

What is promise all in JavaScript?

all() The Promise. all() method takes an iterable of promises as an input, and returns a single Promise that resolves to an array of the results of the input promises. This returned promise will fulfill when all of the input's promises have fulfilled, or if the input iterable contains no promises.


1 Answers

You need to collect all of your promises in an array and then use Promise.all:

// Example of gathering latest Stack Exchange questions across multiple sites  // Helpers for example  const apiUrl = 'https://api.stackexchange.com/2.2/questions?pagesize=1&order=desc&sort=activity&site=',      sites = ['stackoverflow', 'ubuntu', 'superuser'],      myArrayOfData = sites.map(function (site) {          return {webAddress: apiUrl + site};      });    function convertToStringValue(obj) {      return JSON.stringify(obj, null, '\t');  }    // Original question code  let mainObject = {},      promises = [];    myArrayOfData.forEach(function (singleElement) {      const myUrl = singleElement.webAddress;      promises.push(axios.get(myUrl));  });    Promise.all(promises).then(function (results) {      results.forEach(function (response) {          const question = response.data.items[0];          mainObject[question.question_id] = {              title: question.title,              link: question.link          };      });        console.log(convertToStringValue(mainObject));  });
<script src="https://unpkg.com/[email protected]/dist/axios.min.js"></script>

It's described in axios docs (Performing multiple concurrent requests section).

Before May 2020 it was possible to do with axios.all(), which is now deprecated.

like image 129
krasu Avatar answered Sep 28 '22 02:09

krasu