JavaScript is single-threaded. All foreach loops complete before asynchronous APIs resolve results. On the other hand, a foreach loop can push an array of promises that can be used to chain subsequent code:
var promiseArray=[];
angular.forEach(vm.tableJson, function(value1, key1){
if(value1.Type != 'table'){
if(key == 0){
vm.columns.push(value1.Name);
}
cell.push(value[value1.Settings[1].Value]);
promiseArray.push(key1);
}
else{
var promise = reportService.getInnerTableRecords(aaa);
var newPromise = promise.then(function(dataRes){ //server call
angular.forEach(dataRes.rows, function(value2, key2){
//some code
})
return key1;
});
promiseArray.push(newPromise);
}
});
var compositePromise = $q.all(promiseArray);
return compositePromise.then(function(keyArray) {
console.log("Number of processed keys = " + keyArray.length);
//
//Do subsequent processing here
}).catch(function(error) {
console.error(error)
throw error;
});
In the above example the composite promise resolves to an array of the keys for the loop. Each iteration of the loop pushes a promise to an array. The composite promise is created with $q.all. The composite promise is then used to chain subsequent code.
Be sure to return promises from nested levels. Otherwise parent promises will resolve before nested levels complete.
Chaining promises
Because calling the .then
method of a promise returns a new derived promise, it is easily possible to create a chain of promises.
It is possible to create chains of any length and since a promise can be resolved with another promise (which will defer its resolution further), it is possible to pause/defer resolution of the promises at any point in the chain. This makes it possible to implement powerful APIs.
--AngularJS $q Service API Reference -- Chaining Promises