forEach
is a synchronous operation. So when your resolve() is called then it is guaranteed that all iterations have already run.
However it would seem that you intend to perform some asynchronous operation in each iteration, and would like to wait for all of them to complete. This can be elegantly handled through promises.
Let us say that you have a downloadFile
asynchronous function that returns a promise (if not, use promisify), you can map the arrayOfFiles to the array of promises and use Promise.all
to combine the array of promises to a single promise that is resolved if all the promises in the array have resolved.
return $q(function (resolve, reject) {
var arrayOfPromises = _.map(arrayOfFiles, function (file) {
var url = file.link;
return downloadFile(url)
});
Promise
.all(arrayOfPromises)
.then(resolve)
.catch(reject);
});
It should be obvious at this point, that you simply do not need to invoke the promise constructor. You can just write:
return Promise.all(_.map(arrayOfFiles, function (file) {
return downloadFile(file.link)
}))
This can be made more succinct taking advantage of ES6 features:
return Promise.all(arrayOfFiles.map(({ link }) => downloadFile(link)))
In fact explicitly creating promises should be considered an anti-pattern. Relying on promise composition utilities is almost always a better practice.