How is Javascript asynchronous and single-threaded in same time?
The answer is Javascript is single=threaded, but not quite asynchronous. Asynchronous tasks are handled by the environment around Javascript like browser for example. Browser contains Web APIs, Task queue, Microtask queue, and Event loop which handles asychronous tasks.
Event loop is a running process that watches call stack & queues. If the call stack is empty, it takes first event in Task queue and pushes it to the call stack.
Tick represents an iteration that event loop executes.
Most asynchronous callbacks like setTimeout
or setInterval
goes to Task queue when it is fired. However, in ES6, Mictrotask queue was introduced as a queue that stores callback from the Promise
object, MutationObserver
, and etc.
console.log('script start');
setTimeout(function () {
console.log('setTimeout');
}, 0);
Promise.resolve()
.then(function () {
console.log('promise1');
})
.then(function () {
console.log('promise2');
});
console.log('script end');
// script start - promise1 - promise2 - setTimeout - script end
Although setTImeout
function's callback is added to Task queue faster than Promise
object's callback, as event loop visits to microtask queue first, Promise
object's callback is pushed to call stack and executed first.
Another point is that promise1 and promise2 logged at one stream. In case of Task queue, event loop only pushes callback to call stack one at a time. However, as it's previously mentioned, mictrotask queue moves stored callbacks to call stack untill it's empty.