1

I'm trying to grok how Promise.all works, and it seems like it ought to be simple. My understanding is that Promise.all takes an array of promises and then executes them all at the same time.

Here's some code I wrote that I execute via node (8.10.0) that I expected would work properly:

const getFirstPromise = function() {
    return new Promise((resolve, reject) => {
        setTimeout(function(){
            console.log("1");
            resolve("First!"); // Yay! Everything went well!
        }, 2500);
    });
};

const getSecondPromise = function() {
    return new Promise((resolve, reject) => {
        setTimeout(function(){
            console.log("2");
            resolve("Second!"); // Yay! Everything went well!
        }, 250);
    });
};

const getThirdPromise = function() {
    return new Promise((resolve, reject) => {
        setTimeout(function(){
            console.log("3");
            resolve("Third!"); // Yay! Everything went well!
        }, 1000);
    });
};

const getFourthPromise = function () {
    return new Promise((resolve, reject) => {
        setTimeout(function(){
            console.log("4");
            resolve("Fourth!"); // Yay! Everything went well!
        }, 500);
    });
};

const tasks = [
    getFirstPromise,
    getSecondPromise,
    getThirdPromise,
    getFourthPromise
];

Promise.all(tasks).then((result) => console.log("Done alling the promises: ", result)).catch(err => console.log(err));

As written, this doesn't execute any of the promises.

If I change the tasks collection to look like this:

const tasks = [
    getFirstPromise(),
    getSecondPromise(),
    getThirdPromise(),
    getFourthPromise()
];

then all of the promises execute, but if I comment out the Promise.all line, they still execute.

What I was expecting was to create a collection of promises that would NOT be run until Promise.all was called.

Please either explain how to achieve what I'm expecting OR explain how my understanding of Promise.all is flawed or tell me how else I should be creating my promises.

I'm not interested in the myriad of other ways of executing this series of promises. I just want to understand how Promise.all should work with a collection of promises in the case where I don't want the promise code to run until Promise.all is executed.

Tad Donaghe
  • 6,625
  • 1
  • 29
  • 64
  • 3
    Well, the quick answer would be to only call your wrappers when calling `Promise.all([ wrapper1(), wrapper2(), ... ])`, because `Promise.all` simply encapsulates all the promises and returns a promise so you don't have to do `Promise.then(() => Promise.then( ... ))` recursively, which would look really shitty. It has no knowledge of wrapper functions, it expects `Promise` objects that have been initialised. – somethinghere Apr 27 '18 at 15:55
  • 1
    _I just want to understand how Promise.all should work with a collection of promises in the case where I don't want the promise code to run until Promise.all is executed._ This is not how Promises are specified to behave. https://stackoverflow.com/questions/42118900/when-is-the-body-of-a-promise-executed – Kevin Boucher Apr 27 '18 at 15:57
  • @somethinghere What's the primary difference between that and my second declaration of the tasks array above? Just that I can .then off of it? – Tad Donaghe Apr 27 '18 at 15:58
  • @KevinBoucher - given that, what's the point of Promise.all? – Tad Donaghe Apr 27 '18 at 15:59
  • 1
    To handle the resolutions (or rejections) all at once. – Kevin Boucher Apr 27 '18 at 16:01
  • 1
    The point of `Promise.all` is that you do not have to keep recursively calling `promises.then` to finish of loading, say, fifty images. Just imagine the nested hell that would generate. Its a Utility function that simply auto-fills a promise with a function that checks for all promises to complete. And the reason I suggested it that way is because then you can execute what you want between that and initialising your promise. In essence it makes no difference. – somethinghere Apr 27 '18 at 16:01
  • 3
    *"what's the point of Promise.all?"* To "wait" for multiple promises to resolve. – Felix Kling Apr 27 '18 at 16:01
  • Ok, thanks guys. I think I've got it! – Tad Donaghe Apr 27 '18 at 16:03
  • As an aside, there was an answer to another SO question which had the pattern I tried above as an answer to a similar question, and I've been frustrated since then since the code provided didn't work. ;) – Tad Donaghe Apr 27 '18 at 16:05
  • 2
    `Promise.all()` doesn't RUN anything. All it does it monitor activities that you've already started. So, if you don't want your async operations to start until later, then don't start them until later. You're starting them as soon as you declare your `tasks` structure. This has nothing at all to do with `Promise.all()`. You called your functions sooner than you want them to run. – jfriend00 Apr 27 '18 at 16:17

1 Answers1

1

You can use this function instead of Promise.all

var Task = {
   all: function(tasks) {
      return Promise.all(tasks.map((task) => task()));
   }
};

and use

const tasks = [
    getFirstPromise,
    getSecondPromise,
    getThirdPromise,
    getFourthPromise
];

Task.all(tasks).then((result) => console.log("Done alling the promises: ", result)).catch(err => console.log(err));
jcubic
  • 61,973
  • 54
  • 229
  • 402
  • This is generally how I solved my actual, work related problem that prompted this in the first place, but it isn't nearly as satisfying as what I tried to do in the first place. :) I think @somethinghere's first comment shines a light on the issue that I missed originally. – Tad Donaghe Apr 27 '18 at 16:02