-1

I'm using Lodash ForeEach and I want to determine when I finish looping and run return resolve promise.

   return $q(function (resolve, reject) {
    _.forEach(arrayOfFiles, function (file) {
      var url = file.link;
      //Download file in device ()
    });

    //her i wont to resolve after finish looping
    resolve()
  })

There is any way to achieve that ?

Nurdindev
  • 173
  • 1
  • 12

3 Answers3

1

You don't need to "determine" anything, any code that follows your _.forEach() would be executed after the looping finishes.

_.forEach(arrayOfFiles, function (file) {
      var url = file.link;
      //Download file in device ()
    });

callAnotherMethod();

PS. Your "Download file in devise" comment suggests that you might be concerned about the asynchronous calls. Well, those will have to be dealt in those asynchronous calls.

Uzbekjon
  • 11,655
  • 3
  • 37
  • 54
0

You need a variable to count finished iterations so that you can check if the counter is equal to the number of elements on which the iterations are processed.

 counter = 0;
 _.forEach(arrayOfFiles, function (file) {
  var url = file.link;
  //Download file in device ()
  counter++;
  if(counter == _.length){
        //it's finished
  }
});
emrhzc
  • 1,347
  • 11
  • 19
0

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.

Community
  • 1
  • 1
lorefnon
  • 12,875
  • 6
  • 61
  • 93