2

I'm trying to understand the whacky world of javascript promises and came across this that I don't understand.

The first program is from a book explaining promise chaining and works just as you would think:

var Promise = require('promise');

function delay(time) {
    return new Promise( function(resolve,reject) {
        setTimeout( resolve, time ); 
    });
}

delay(1000) // step 1
    .then(function STEP2(){
        console.log( "step 2b (after 1000ms)" );
        return delay( 2000 );
    })
    .then(function STEP3(){
        console.log( "step 3b (after another 2000ms)" );
    })
    .then(function STEP4(){
        console.log( "step 4b (next Job)" );
        return delay( 5000 );
    })
    .then(function STEP5() {
        console.log( "step 5b (after another 5000ms)" );
    });

The console logs appear after the correct amount of delays.

NOW, in order to make this clearer in my own mind, I made the STEP functions explicitly so the program now looks like this:

var Promise = require('promise');

function delay(time) {
    return new Promise( function(resolve,reject){
        setTimeout( resolve, time );
    });
}
function STEP2() {
    console.log( "step 2 (after 1000ms)" );
    return delay( 2000 );
}
function STEP3() {
    console.log( "step 3 (after another 2000ms)" );    
}
function STEP4() {
    console.log( "step 4 (next Job)" );
    return delay( 5000 );
}
function STEP5() {
    console.log( "step 5 (after another 5000ms)" );
}

delay( 1000 ).then(STEP2()).then(STEP3()).then(STEP4()).then(STEP5());

But now all the console logs happen at once, the program delays 5000 ms and then exits. Can someone explain what is different (functionally) between the two examples above? Thank you.

Tomalak
  • 306,836
  • 62
  • 485
  • 598
kevdev
  • 157
  • 11
  • 2
    In the first version you're not calling the step functions (just passing them as parameters). – thebjorn Sep 23 '15 at 21:13
  • [Voting to close this as off-topic (#2)](http://stackoverflow.com/help/on-topic). – zzzzBov Sep 23 '15 at 21:17
  • @zzzzBov What part of this question is off-topic for you? – Tomalak Sep 23 '15 at 21:20
  • 2
    @kevdev Hint: You must be able to transform the first sample into the second sample purely by means of copy and paste. If you can't do that, the two code samples are not equivalent. – Tomalak Sep 23 '15 at 21:21
  • There has to be a duplicate target we can use for such a common mistake.. – Kevin B Sep 23 '15 at 21:22
  • @Tomalak, I thought I was clear by linking and then specifying the number to read, but specifically "Questions about a problem that can no longer be reproduced or that was caused by a simple typographical error." The simple typographical error is that there are `()` characters when there should not be `()` characters. – zzzzBov Sep 23 '15 at 21:25
  • @Tomalak, but feel free to mark it as a [duplicate](http://stackoverflow.com/questions/8462381/settimeout-callback-executed-immediately) [of](http://stackoverflow.com/questions/2037203/why-is-my-function-call-that-should-be-scheduled-by-settimeout-executed-immediat) [another](http://stackoverflow.com/questions/3800512/calling-functions-with-settimeout) [question](http://stackoverflow.com/questions/7137401/why-is-the-method-executed-immediately-when-i-use-settimeout?lq=1). – zzzzBov Sep 23 '15 at 21:26
  • @zzzzBov Adding `()` to JS code is not a typographical error. Why would you think that? – Tomalak Sep 23 '15 at 21:26
  • @Tomalak, typing `()` when you shouldn't have is just as much a tyop as misspeeling wrods. – zzzzBov Sep 23 '15 at 21:27
  • 3
    @zzzzBov No. It indicates that you did not understand the fundamental difference between `foo` and `foo()`. And this is a *semantic* mistake, completely different from mistyping the function name or writing `,` instead of `;` in a `for` loop statement. And people asking questions about their semantic mistakes are here to learn, in stark contrast to the "please fix my code" crowd. They are as on topic as it gets. – Tomalak Sep 23 '15 at 21:31
  • 1
    No. It is not a typographical error - because, up until now, I did not know it made a difference as to when a function is run between it being passed as parameter or being called. I naively thought that the STEP() functions would be called after the delay. Certainly not a typo. – kevdev Sep 23 '15 at 21:36

1 Answers1

6

In your first example, you are passing in a function. In your second example, you are passing in the result of the function since you included the () after the function name.

This is probably what you're looking to do:

delay( 1000 ).then(STEP2).then(STEP3).then(STEP4).then(STEP5);
Anid Monsur
  • 4,553
  • 1
  • 15
  • 24
  • Well that certainly did the trick but leaves me still confused. It can be boiled down to this: delay(2000).then(function () {console.log("After 2000ms")}); works but `delay(2000).then(console.log("After 2000ms"));' doesn't – kevdev Sep 23 '15 at 21:26
  • 2
    @kevdev - you have to pass a function reference so that the promise infrastructure can call it later. `function () {console.log("After 2000ms")}` is a function reference. `console.log("After 2000ms")` is not a function reference. That runs `console.log()` immediately and passes the return result from executing it which is `undefined`. – jfriend00 Sep 23 '15 at 22:49