How to use a promise for forach loop to populate an object

I run a forEach loop in an array and make two calls that return promises, and I want to populate the say this.options object and then do other things with it. Right now I am encountering the async problem if I use the following code sample and I enter the then function first.

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

This is the working code below, but it only works for the first element in the array, because I call the resulting function in the .then response. I want to do all the first selection 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 to populate the self.files object after the forEach loop completes, and then call the resulting function with the file object?

+7
javascript arrays promise foreach es6-promise
source share
4 answers

Promise.all() will be useful 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 causes an AJAX call for each of the elements, after the call is completed, adds the result of each call to self.files and calls self.resultingFunction() after all the calls are completed.

Edit: Simplified based on the suggestions of Yuri Tarabanko.

+20
source share

Just a small variation of the decision made above:

 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) ); 
+3
source share

The following code is a simple understanding of synchronization using Promise.

 let numArr = [1,2,3,4,5]; let nums=[]; let promiseList = new Promise(function(resolve,reject){ setTimeout(()=>{ numArr.forEach((val)=>{ nums.push(val); }); resolve(nums); },5000) }) Promise.all([promiseList]).then((arrList)=>{ arrList.forEach((array)=>{ console.log("Array return from promiseList object ",array); }) }); 

In the above example, the array will contain the nums array for 5 seconds. and it will print to the console after its release.

+1
source share

You can see this answer to a similar question for a great hint. The solution there uses Array#reduce() to avoid having to accumulate all Promises before doing any work, rather than using Promise.all() .

0
source share

All Articles