0

I am new to JS and was learning Promises. The confusion I faced is that callback in then() is pushed into job queue. Here is an example:

 let promise = new Promise((resolve, reject) => {
       resolve(setTimeout(()=>console.log('Done'),2000))
    })
    .then((data) => {           
      data;
    })

So, we have promise which is resolved with console.log('Done'). After that, console.log('Done') is passed to then() and callback in then() is passed to job queue. Why? after we are given the data from asynchronous setTimeout, why need to pass callback in then() to job queue?

Edited

Say we have the following code:

let promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('foo');
    }, 2000);
})
.then((data) => {
    console.log(`resolved value: ${data}`);
    return 'bar';
})

Does the above code work like this. First, when the code is executed, JS engine encounters promise and setTimeout inside. Then, setTimeout is pushed into Web Api then JS engine continues executing the code and encounters then and its callback. Then then's callback is pushed into job queue and waits until promise is resolved. Is that correct?

Dickens
  • 895
  • 3
  • 11
  • 25
  • What are you trying to accomplish? – Dominik Matis Nov 16 '19 at 06:16
  • 1
    `setTimeout()` returns a timerID and then executes it's timer callback sometime later. So, that means that you are resolving the promise IMMEDIATELY with the timerID as the resolved value and the timer callback gets called 2 seconds later. Meanwhile, since the promise is resolved, the `.then()` handler gets called. ALL `.then()` handlers execute on a future tick, not synchronously. That's how the promise specification is written. – jfriend00 Nov 16 '19 at 06:29
  • Your example doesn't really make sense, as the timeout has nothing to do with the (immediate!) promise resolution. If that was only a mistake and you really meant to ask the titular question, see [What is the intention behind clause 2.2.4 of Promise/A+ spec?](https://stackoverflow.com/questions/36932244/what-is-the-intention-behind-clause-2-2-4-of-promise-a-spec) – Bergi Nov 16 '19 at 19:09
  • @Bergi, hi thank you for your kind comments, I just wanted to understand why callback of then() is executed via Job queue. Is it true that the reason for that is callback can be asynchronous, e.g. .then((data) => { return setTimeout(data); }). If so, then what if we do not use asynchronous code and just use .then((data) => { data; }) then what is the point of executing this callback via job queue since it is just synchronous – Dickens Nov 17 '19 at 05:21
  • No, it doesn't matter whether the callback does something asynchronous or not. The point of being executed via the job queue is that the *promise* on which it was installed does resolve asynchronously. – Bergi Nov 17 '19 at 05:42
  • @Bergi, I read here https://medium.com/@Rahulx1/understanding-event-loop-call-stack-event-job-queue-in-javascript-63dcd2c71ecd that "these thenable methods are added to Job Queue, and gets executed once the promise has returned/resolved". So, it means callback of then() awaits in Job queue until promise resolves right? – Dickens Nov 17 '19 at 07:35
  • @Bergi, I added some more info to my question. Please can you give your kind comments if it is true the way how I understand job queue – Dickens Nov 17 '19 at 08:32
  • @Dickens That article is riddled with inaccuracies. The statement you quoted makes no sense at all. Find a better article about the event loop. When you call `promise.then(onFulfilled)`, the `onFulfilled` callback is first stored in the promise itself. Then, *when the promise fulfills*, this callback function (and the promise result as the argument) get scheduled on the job queue. – Bergi Nov 17 '19 at 14:51
  • @Bergi, by the way dude, you are not the first dev who says that the article shared have inaccuracies. Please can you tell how it is possible to differentiate good proper articles with bad articles to learn properly. Should we pay attention to CLAPS that article gets? – Dickens Nov 17 '19 at 18:24
  • 1
    @Dickens No idea, I think that's still an unsolved problem. Building up a personal metric for reputability of sources comes with time… Thinks like claps/votes, comments, or even the quality of spelling can be indicators. – Bergi Nov 17 '19 at 18:32

2 Answers2

1

I'm not sure this code is behaving how you think it is.

let promise = new Promise((resolve, reject) => {
    resolve(setTimeout(()=>console.log('Done'),2000))
})
.then((data) => {
    data;
})

This promise is resolving immediately with the result of the setTimeout call. This can be demonstrated by adding a log to your then callback:

.then((data) => {
    console.log('data', data);
    data;
})

This example might help:

let promise = new Promise((resolve, reject) => {
    console.log('one');
    setTimeout(() => {
        console.log('three');
        resolve('foo');
        console.log('four');
    }, 2000);
    console.log('two');
})
.then((data) => {
    console.log(`resolved value: ${data}`);
    return 'bar';
})

promise.then(data => console.log(`resolved value: ${data}`));
Andy Gaskell
  • 31,495
  • 6
  • 74
  • 83
  • hey Andy thanks for your kind answer, I just wanted to understand why callback of then() is passed into job queue. Since then()'s callback is executed only after we got data from asynchronous operation. I just logically cannot get the reason for passing then()'s callback into job queue after having gotten the data – Dickens Nov 16 '19 at 07:10
  • please I really need your help (( – Dickens Nov 16 '19 at 11:12
  • I guess the first reason is that it's in the specification - https://www.ecma-international.org/ecma-262/6.0/#sec-promise-objects. To me this makes more sense than changing the current call stack, especially since we're just passing a function, not calling it. It's also possible that you callback will be asynchronous - would executing immediately make sense in that case? – Andy Gaskell Nov 16 '19 at 15:41
0

A promise is defined as an object that has a function as the value for the property then:

then (fulfilledHandler, errorHandler, progressHandler)

This function should return a new promise that is fulfilled when the given fulfilledHandler or errorHandler callback is finished. This allows promise operations to be chained together. The value returned from the callback handler is the fulfillment value for the returned promise. If the callback throws an error, the returned promise will be moved to failed state.

In other words, then is not a mechanism for attaching callbacks; It's a mechanism for applying a transformation to a promise, and yielding a new promise from that transformation.

ObjectMatrix
  • 325
  • 1
  • 3
  • 9