1

I have an array of images that get uploaded with a chain of async operations like so:

for ( var key in imageFileObject ) {
  const imageFile = imageFileObject[key]
  dispatch('get_signed_request', imageFile)
}

Each dispatch triggers a multitude of other async operations.

I'd like to know when all the operations are done so that I could take some action.

How can this be achieved?

softcode
  • 4,358
  • 12
  • 41
  • 68
  • For waiting on multiple async operations look at this for an idea of how to do it: http://stackoverflow.com/questions/4631774/coordinating-parallel-execution-in-node-js/4631909#4631909. Basically you have to keep track of how many have started and how many have completed. Then instead of writing the logic yourself check out the async.js library – slebetman Jan 27 '17 at 01:13
  • 1
    If `imageFileObject` is an array, then you should use `for of` not `for in`. – jib Jan 27 '17 at 03:03
  • @jib why ? what's the difference in this case – softcode Jan 27 '17 at 04:09
  • @softcode See http://stackoverflow.com/questions/500504/why-is-using-for-in-with-array-iteration-a-bad-idea – jib Jan 27 '17 at 05:13
  • @jib awesome thanks for the help ! – softcode Jan 27 '17 at 05:31

3 Answers3

2

Try this:

let totalImagesLeft = Object.keys(imageFileObject).length;

for ( var key in imageFileObject ) {
  const imageFile = imageFileObject[key]
  dispatch('get_signed_request', imageFile).then((res)=>{
     totalImagesLeft --;
     if(totalImagesLeft === 0){
        // done
     } 
  });
}

Example you can paste in console that shows it works:

var async = () => {
   return new Promise((resolve,reject)=>{
          setTimeout(()=>{ console.log("done"); resolve() },1000);
   });
}

let test = [async,async,async];


let totalImagesLeft = test.length;

for ( let t of test ) { 
  t().then((res)=>{
     totalImagesLeft --;
     if(totalImagesLeft === 0){
        console.log("finished");
     } 
  });
}
Sumama Waheed
  • 3,579
  • 3
  • 18
  • 32
1

If imageFileArray is an array, and dispatch returns a promise, then just do:

Promise.all(imageFileArray.map(file => dispatch('get_signed_request', file)))
  .then(results => console.log("finished"));
jib
  • 40,579
  • 17
  • 100
  • 158
  • `console.log("finished")` runs before a lot of other code being dispatched – softcode Jan 27 '17 at 16:29
  • @softcode Not if you return every promise. Note that in the code above, the return is implicit with arrow functions, so if you're using regular functions, remember to return everything explicitly. e.g. `array.map(function(file) { return dispatch('get_signed_request', file); })`. If you forget, to do this, the chain is broken and won't wait for everything before proceeding. – jib Jan 27 '17 at 18:16
1

You can use the Promisse.all, it returns a promise that resolves when all of the promises in the iterable argument have resolved, or rejects with the reason of the first passed promise that rejects.

Mozilla documentation here.

Promise
    .all(fileArray.map(file => dispatch('get_signed_request', file)))
    .then(data => console.log("All your async operations are finished"));
Pedro Rodrigues
  • 1,662
  • 15
  • 19