11

Basic promise question:

console.log('Promise START');

function makeFullJSON(time) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, time, [time]);
  })
}

var p1 = makeFullJSON(1000);
var p2 = makeFullJSON(500);
var p3 = makeFullJSON(750);

p1.then(array => {
  console.log('Promise 1 complete', array);
});

p2.then(array => {
  console.log('Promise 2 complete', array);
});

p3.then(array => {
  console.log('Promise 3 complete', array);
});

Promise.all([p1, p2, p3]).then(arrayOfAllResolvedValues => {
  console.log('Array of resolved values:', arrayOfAllResolvedValues);
});

console.log('Promise END');

The code output is:

Promise START
Promise END
Promise 2 complete [ 500 ]
Promise 3 complete [ 750 ]
Promise 1 complete [ 1000 ]
Array of resolved values: [ [ 1000 ], [ 500 ], [ 750 ] ]

How do you rewrite the code, such that output is:

Promise START
Promise 2 complete [ 500 ]
Promise 3 complete [ 750 ]
Promise 1 complete [ 1000 ]
Array of resolved values: [ [ 1000 ], [ 500 ], [ 750 ] ]
Promise END
Michael
  • 8,362
  • 6
  • 61
  • 88
S. Vaghar
  • 191
  • 1
  • 1
  • 7
  • sounds like a duplicate of: http://stackoverflow.com/q/14220321/497418. – zzzzBov Mar 09 '17 at 02:04
  • Just put the *Promise END* `console.log` next to the *resolved values* one? – Bergi Mar 09 '17 at 02:04
  • `Promise.all([p1, p2, p3]).then(() => console.log('Promise END'))` – Thomas Mar 09 '17 at 02:16
  • You can't ever cause the interpreter in Javascript to "wait" for any async operation. Instead, you do what you always do in any single-threaded, event-driven system - you register a callback to get notified when the operation is done and you carry out your work in that callback. You don't "wait" in Javascript. – jfriend00 Mar 09 '17 at 06:27
  • Thanks all. I agree with the callback notification. That seems to be the only way for now (until i get to use async await pattern). – S. Vaghar Mar 09 '17 at 17:53

4 Answers4

7

Anything that you want to happen after the completion goes in the arrow function that you pass to then.

    console.log('Promise START')
    
    function makeFullJSON(time) {
       return new Promise((resolve, reject) => {
       setTimeout(resolve, time, [time])
    })}
    
    var p1 = makeFullJSON(1000)
    var p2 = makeFullJSON(500)
    var p3 = makeFullJSON(750)
    
    p1.then(array => {
        console.log('Promise 1 complete', array)})
    
    p2.then(array => {
        console.log('Promise 2 complete', array)})
    
    p3.then(array => {
        console.log('Promise 3 complete', array)})
    
    Promise.all([p1, p2, p3]).then(arrayOfAllResolvedValues => {
        console.log('Array of resolved values:', arrayOfAllResolvedValues)
    
        console.log('Promise END')
    })

In order to abandon immediate program execution, and start writing code which would happen only after all 3 promises resolve, as it sounds like you want to happen, then I would recommend creating a new function directly below your code, to contain code which you would like to happen after resolution, and pass that function like: Promise.all([p1, p2, p3]).then(newFunctionName). It might be easier for you to visualize it that way, at least until you get used to thinking about how it works precisely.

fatal_error
  • 5,457
  • 2
  • 18
  • 18
Kent Weigel
  • 1,168
  • 1
  • 11
  • 16
2

First fix the syntax error. Then move the console.log to where the entire process ends:

console.log('Promise START');

function makeFullJSON(time) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, time, [time]);
  })}

var p1 = makeFullJSON(1000);
var p2 = makeFullJSON(500);
var p3 = makeFullJSON(750);

p1.then(array => {
  console.log('Promise 1 complete', array);});

p2.then(array => {
  console.log('Promise 2 complete', array);});  // fixed syntax error here

p3.then(array => {
  console.log('Promise 3 complete', array);});

Promise.all([p1, p2, p3]).then(arrayOfAllResolvedValues => {
  console.log('Array of resolved values:', arrayOfAllResolvedValues);
  console.log('Promise END');
});
rasmeister
  • 1,986
  • 1
  • 13
  • 19
1

If the obvious answer of placing the console.log('Promise END') doesnt float your boat, why not this?

//didnt change anything at all above here
Promise.all([p1, p2, p3]).then(arrayOfAllResolvedValues => {
    console.log('Array of resolved values:', arrayOfAllResolvedValues);
}).then(() => {
    console.log('Promise END');
});

If you want to sequence an operation after all promises were fulfilled, you have to sequence with then() just as you are doing when you print your array values

JSelser
  • 3,510
  • 1
  • 19
  • 40
0

Use async/await:

(async () => {
  console.log('Promise START');

  function makeFullJSON(time) {
    return new Promise((resolve, reject) => {
    setTimeout(resolve, time, [time]); 
  })}

  var p1 = makeFullJSON(1000);
  var p2 = makeFullJSON(500);
  var p3 = makeFullJSON(750);

  p1.then(array => {
    console.log('Promise 1 complete', array);});

  p2.then(array => {
    console.log('Promise 2 complete', array);});

  p3.then(array => {
    console.log('Promise 3 complete', array);});

  console.log('Array of resolved values:', await Promise.all([p1, p2, p3]));

  console.log('Promise END');
})();
jib
  • 40,579
  • 17
  • 100
  • 158
  • 1
    Thanks everyone for all your comments. The issue is that, what if the above code is in function A that is called by another function B. Function B needs all the promises to finish after calling A, for it to continue. This is similar to await pattern. The only way I know to solve this problem (without await) is to pass a callback to function A and called it in Promise.all (as was suggested). A am I correct? – S. Vaghar Mar 10 '17 at 17:37
  • @S.Vaghar Have function A return the promise from `Promise.all`? – jib Mar 10 '17 at 18:30