I have the following code, which does not work as I expect.
const bar = () => console.log('bar')
const baz = () => console.log('baz')
const myPromise = new Promise((resolve, reject) =>
resolve('should be right after baz, before bar')
);
const foo = () => {
console.log('foo')
setTimeout(bar, 0)
myPromise.then(resolve => console.log(resolve))
baz()
}
foo()
console.log('before bar')
The result:
foo
baz
before bar
should be right after baz, before bar
bar
According to what's written in https://nodejs.dev/ , promise resolve will happen right after the function.
Promises that resolve before the current function ends will be executed right after the current function.
So I expect 'should be right after baz, before bar' to happen right after the end of foo()
, before console.log('before bar')
.
Can someone explain why it doesn't?
Callbacks passed to setTimeout
are added in the task queue whereas the callbacks related to promise fulfilment or rejection are added in the micro-task queue.
These queues are only processed after the synchronous execution of your script, i.e. the javascript code you wrote.
As a result, 'before bar'
is logged before any asynchronous callbacks are invoked.
Script execution starts.
Function bar
, baz
, and foo
are defined. Promise constructor is also called which leads to the invocation of resolve
function, resolving the promise synchronously
foo
function is called
'foo'
is logged on the consolesetTimeout
is called, scheduling bar
to be called asynchronously. bar
will be added in the task queuethen
method is called on myPromise
, scheduling the fulfilment handler to be invoked asynchronously. This fulfilment handler is added in the micro-task queuebaz
function is called, logging 'baz'
on the consolefoo
function ends. Control return to the next line from where foo
was called
Last console.log
statement is executed, logging 'before bar'
on the console
Script execution ends
At this point, console output is as shown below:
foo
baz
before bar
and the task queue contains a task to execute the bar
function whereas the micro-task queue contans a micro-task to execute the fulfilment handler of the myPromise
.
After the script execution ends, task and micro-task queues can be processed.
The micro-task queue is processed:
Script execution is a task and after its execution, micro-task queue will be the first one to be processed, logging 'should be right after baz, before bar'
on the console.
At last, the task queue is processed, baz
function is called, logging 'baz'
on the console.
Following might be a helpful read to understand the micro-task and the task queue: JavaScript async callbacks - Promise and setTimeout