Christian68
Christian68

Reputation: 995

Promise starts too early

I have the following promise:

const promise = new Promise((resolve,reject) => {
  setTimeout(()=> { resolve('Hello')},4000);
});

And later, I call it like this:

promise.then((msg) => {console.log(msg)});

I was expecting that the 'Hello' message is displayed 4 seconds after the call to then due to the timeout, but it is actually displayed right away...

It is sure something I'm missing: what?

Upvotes: 0

Views: 235

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074168

And I call it like this

You don't "call" a promise. It's not a function (though it does have methods). From the question I understand that you did the first part (const promise = new Promise(/*...*/);), and then later did the second part (promise.then(/*...*/);), and you expected the timer to start when you did then, not when you did new Promise.

But the way Promises work, your timer was started when you did new Promise, not later when you called then. The function you pass into new Promise (the promise executor function) is called synchronously and immediately. Its purpose is to start the operation that the promise is going to report the completion of.

This may help make it a bit more clear:

const start = Date.now();
function log(msg) {
    const elapsed = String(Date.now() - start).padStart(4, " ");
    console.log(`${elapsed}: ${msg}`);
}

log("A");
const promise = new Promise((resolve, reject) => {
    log("B: Starting 5000ms timer");
    setTimeout(() => {
        resolve("Hello");
    }, 5000);
    log("C");
});
log("D: Waiting 2000ms before calling `then`");
setTimeout(() => {
    log("F: Calling `then`");
    promise.then((msg) => {
        log("G");
        log(msg)
    });
}, 2000);
log("E");

Notice that the output is

   0: A
   1: B: Starting 5000ms timer
   2: C
   2: D: Waiting 2000ms before calling `then`
   2: E

and then about two seconds later:

2002: F: Calling `then`

and then about three seconds later (five seconds since the start)

5002: G
5004: Hello

Things to note:

  • The promise executor was run synchronously and immediately, and start its 5 second timer
  • It doesn't matter when you call then. I waited to call then for 2 seconds, but still got the fulfillment callback after a total of 5 (not 7) seconds

What I describe above is the standard behavior for promises. There are (unfortunately, in my view) a small number of promise-like things out there that behave slightly differently, that do wait for the first call to then before they start their process. Those are not typical, but sadly they do exist.

Upvotes: 5

Related Questions