Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use promise in forEach loop of array to populate an object

I am running a forEach loop on an array and making two calls which return promises, and I want to populate an object say this.options, and then do other stuff with it. Right now I am running into the async issue if i use the following code sample and i get into the then function first.

$.when.apply($, someArray.map(function(item) {     return $.ajax({...}).then(function(data){...}); })).then(function() {     // all ajax calls done now }); 

This is working code below, but it only works for the first element in the array, because I call the resulting function in the .then of the response. I want to do all the fetch first for all elements of the array and then call the resulting function to do something.

array.forEach(function(element) {     return developer.getResources(element)         .then((data) = > {             name = data.items[0];             return developer.getResourceContent(element, file);         })         .then((response) = > {             fileContent = atob(response.content);             self.files.push({                 fileName: fileName,                 fileType: fileType,                 content: fileContent             });             self.resultingFunction(self.files)         }).catch ((error) = > {             console.log('Error: ', error);         }) }); 

How do i populate the self.files object after the forEach loop is complete, and then call the resulting function with the files object?

like image 940
xyzzz Avatar asked Jul 13 '16 21:07

xyzzz


People also ask

Does forEach return promise?

JavaScript Promises forEach with promises It is possible to effectively apply a function ( cb ) which returns a promise to each element of an array, with each element waiting to be processed until the previous element is processed.

Can you use a forEach loop on an object?

JavaScript's Array#forEach() function lets you iterate over an array, but not over an object. But you can iterate over a JavaScript object using forEach() if you transform the object into an array first, using Object. keys() , Object. values() , or Object.

How do you put a promise inside 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.

Can you use a forEach loop on an array?

The forEach method is also used to loop through arrays, but it uses a function differently than the classic "for loop". The forEach method passes a callback function for each element of an array together with the following parameters: Current Value (required) - The value of the current array element.


2 Answers

Promise.all() will be helpful here:

var promises = [];  array.forEach(function(element) {     promises.push(         developer.getResources(element)             .then((data) = > {                 name = data.items[0];                 return developer.getResourceContent(element, file);             })             .then((response) = > {                 fileContent = atob(response.content);                 self.files.push({                     fileName: fileName,                     fileType: fileType,                     content: fileContent                 });             }).catch ((error) = > {                 console.log('Error: ', error);             })     ); });  Promise.all(promises).then(() =>      self.resultingFunction(self.files) ); 

This starts the AJAX call for each of the items, adds the result of each call to self.files once the call is complete and calls self.resultingFunction() after all calls have been completed.

Edit: Simplified based on Yury Tarabanko's suggestions.

like image 116
TimoStaudinger Avatar answered Oct 11 '22 11:10

TimoStaudinger


Just a slight variation of the accepted solution above would be:

var promises = array.map(function(element) {       return developer.getResources(element)           .then((data) = > {               name = data.items[0];               return developer.getResourceContent(element, file);           })           .then((response) = > {               fileContent = atob(response.content);               self.files.push({                   fileName: fileName,                   fileType: fileType,                   content: fileContent               });           }).catch ((error) = > {               console.log('Error: ', error);           }) });  Promise.all(promises).then(() =>      self.resultingFunction(self.files) ); 

I used Array.map instead of Array.forEach, which means I don't need to create an empty array first, I just re-use the existing one.

like image 37
IonicBurger Avatar answered Oct 11 '22 09:10

IonicBurger