Recently reading Event Loop, Promises, Task Queues, Call Stack, and Web APIs in Js. Just jotting down some notes.
JavaScript
Js is single-threaded, when handling long-running tasks it could block the main thread, causing the UI to freeze. To avoid this, Js uses the following mechanisms to handle async tasks.
Call Stack
When a function is called, it is pushed onto the call stack. When the function returns, it is popped out of the stack.
Web APIs
Web APIs are provided by the browser, such as setTimeout
, fetch
, DOM
, getting your location info, etc. They provide a way to handle async tasks. When an async task is called, the task is pushed to the Web API, and the call stack continues to execute the next function. This kind of async tasks will generate a callback function, the calllback will be pushed to the task queue, NOT the call stack!
Event Loop
The event loop constantly checks the call stack whether it is empty. When it’s empty, it will push the first task in the task queue (callback queue) to the call stack. Callback functions won’t be immediately executed after the async task is done, they should wait for the call stack to be empty. This can prevent unexected disruptions to the call stack.
e.g.
|
|
The output will be 1 3 2
. The 100ms timeout doesn’t really mean the console.log(2)
will be executed after 100ms, it means the callback will be pushed to the task queue after 100ms, so if the call stack is filled with other functions, it might take longer to execute the callback.
(Macro)Task Queue and Microtask Queue
As described above, Task Queue is for callback functions generated by Web APIs, while Microtask Queue is for callback functions generated by Promise
. Microtask Queue has higher priority than Task Queue.
While call stack is empty, the Event Loop will move on to the task queue only when the Microtask Queue is empty. Starvation may occur if the Microtask Queue is always filled with tasks(like infinite loop)
Promise
Promise
is a way to handle async tasks in Js, such as fetch
. It has 3 fields: state
, result
, and Reactions
.
In a Promise
constructor, we pass a callback function with two parameters: resolve
and reject
.
|
|
state
A Promise
has three states: pending
, fulfilled
, and rejected
. If the Promise
is resolved, it will be fulfilled, otherwise it will be rejected.
result
The result of the callback function. If the callback function throws an error , the Promise
will be rejected, this field will be set to the value we passed to reject
. Similarly if the Promise
is resolved this value will be set to the value we passed to resolved
, and the fullfilledReactions
will be enqueued to the Microtask Queue.
BTW, if the state is pending
, the result
field will be undefined
.
Promise Reactions
PromiseFullfillReactions
Callback functions that will be executed when the Promise
is fulfilled, pushed to the Microtask Queue. We can create this reaction by chaining the Promise
with .then()
containing a handler function.
PromiseRejectReactions
Callback functions executed when the Promise
is rejected, pushed to the Microtask Queue. We can create this reaction by chaining the Promise
with .catch()
.
example use:
|
|
another example:
|
|