4

I have some promises and a Promise.all:

array = [];


  var one = new Promise(function(resolve, reject) {
    // Do stuff
    setTimeout(function() {
      resolve('One Done');
      array.push('one');
    }, 5000);
  });


  var two = new Promise(function(resolve, reject) {
    // Do Stuff
    resolve('Two Done');
    array.push('two');
  });


  Promise.all(array).then(values => {
    console.log(values);
  });

We know this doesn't work because array.push needs to be outside.

I currently have a few functions which I need to have called by promises so that finally I can have it in Promise.all.

Would it be advisable to call the function from inside the promise like this:

    function dosomething() {
        // does something
        array.push('something');
    }

  var mypromise = new Promise(function(resolve, reject) {
    dosomething();
    resolve('Did something');
  });

Or is there a more advisable way to do this?

3 Answers3

9

Promise.all waits for an array of Promises. In your example, you are always pushing string types into an array. This obviously won't work. In your first example, you want to push the promises themselves:

array = [];


  var one = new Promise(function(resolve, reject) {
    // Do stuff
    setTimeout(function() {
      resolve('One Done');
    }, 5000);
  });

  array.push(one);


  var two = new Promise(function(resolve, reject) {
    // Do Stuff
    resolve('Two Done');
  });

  array.push(two);

  Promise.all(array).then(values => {
    console.log(values);
  });

As long as the array contains Promise objects, Promise.all will work as expected.

Davin Tryon
  • 66,517
  • 15
  • 143
  • 132
  • Issue is I don't want to pass 'one' or 'two' to promise.all ... I want to push another value into promise.all array from each promise for example array.push('something'); –  Jun 30 '18 at 10:29
3

Promise.All expects an array of promises, and will wait until all promises are fullfilled, providing you with the results of each Promise or a catch if any of them fails.

You can resolve them with any type of object if you are willing to resolve it with more than just a string, and you can use the results afterwards in any way you want, so you could avoid messing with the array inside from the promise and instead resolve the "work item" as a unit and use all required results after the async evaluation.

This will also ( i think ) make the code cleaner and more managable.

You could instead try to do this:

   var valuesArray=[];

   var prom1 = new Promise(function(resolve, reject) {
        // Do stuff
        setTimeout(function() {
          resolve({ msg: 'One Done', data : 'one'});
          // array.push('one');
        }, 5000);
      });

    var prom2 = new Promise(function(resolve, reject) {
        // Do Stuff
        resolve({ msg: 'Two Done', data : 'two'});
        // array.push('two');
      });

   var promisesArray= [prom1,prom2]; 

   Promise.all(promisesArray).then(values => {
        // do stuff with values here
        console.log(values[0].msg);
        console.log(values[1].msg);
        valuesArray.push(values[0].data);
        valuesArray.push(values[0].data);
      });
MKougiouris
  • 2,821
  • 1
  • 16
  • 19
0

I think it would be clearest if you called Promise.all with the array of Promises, with each Promise resolving to the desired value, no outer array nor push at all:

var one = new Promise(function(resolve, reject) {
  // Do stuff
  setTimeout(function() {
    console.log('One Done')
    resolve('one');
  }, 1000);
});


var two = new Promise(function(resolve, reject) {
  // Do Stuff
  console.log('Two Done');
  resolve('two');
});


Promise.all([one, two]).then(arr => {
  console.log(arr);
});

If you need both values (the 'One Done' and the 'one'), you can resolve the initial promises with an array with both values, doing whatever you need to with the 'One Done', and then resolving with the 'one' to be chained with array created by Promise.all:

const logAndReturn = ([logStr, finalResolveStr]) => {
  console.log(logStr);
  return finalResolveStr;
}
var one = new Promise(function(resolve, reject) {
  // Do stuff
  setTimeout(function() {
    resolve(['One Done', 'one']);
  }, 1000);
});


var two = new Promise(function(resolve, reject) {
  // Do Stuff
  resolve(['Two Done', 'two']);
});


Promise.all([
  one.then(logAndReturn),
  two.then(logAndReturn),
]).then(arr => {
  console.log(arr);
});
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • Issue is I don't want to pass 'one' or 'two' to promise.all ... I want to push another value into promise.all array from each promise for example array.push('something'); –  Jun 30 '18 at 10:30
  • Then just call `then` with the `dosomething` and return the `something` from `dosomething`, and it'll be present in the final array. – CertainPerformance Jun 30 '18 at 10:31