preface
Some time-consuming tasks, such as setTimeout, network requests, etc., are often required to wait, but this does not block “single-threaded” JS because of Eventloop.
Let’s start with a few basic concepts.
Single and multi-threaded
One of the most common features of JavaScript is “single threaded,” so why isn’t it multi-threaded? If you think about JavaScript as a browser scripting language, it’s used to interact with pages and manipulate the DOM. If you have multiple threads working on a page at the same time, the page will be in a mess.
Heap, stack, and queue
- Heap: Tree structure with maximum Heap and minimum Heap
- Stack: FILO (first in, last out)
- Queue: FIFO (First in, first out)
JS Event Loop
The event loop mechanism is controlled by the event-triggered thread. All tasks are waiting for the main thread to execute in the call stack. The function that is executed first is pushed to the top of the stack.
Synchronization task
Function calls are simpler when only the synchronization task is used. Here is an example:
function multiply(a, b) {
return a * b
}
function square(a) {
return multiply(a, a)
}
function printSquare(a) {
let result = square(a)
console.log(result)
}
printSquare(10)
Copy the code
Push and exit sequence:
Multiply out the stack according to stack FILO until the stack is cleared.
Asynchronous tasks
The following code adds setTimeout, Promise
console.log(1)
setTimeout(() = > {
console.log(2)},0)
Promise.resolve().then(res= > {
console.log(3)
}).then(res= > {
console.log(4)})console.log(5)
Copy the code
You know that the prints are not sequential, but 1, 5, 3, 4, 2. SetTimeout and Promise are asynchronous, so it’s not just a stack issue here, although eventually they are executed in the stack. How does the js runtime mechanism work?
In the js main thread, the Heap is mainly responsible for memory allocation. Here we focus on the call stack.
Combined with the above graphical model, how does the above example of asynchronous tasks work?
- Js starts execution.
- Console.log (1) pushes the stack and prints 1
- Console. log(1) off the stack, setTimeout on the stack
- The setTimeout callback goes into the Web APIs provided by the browser, its callback goes into the macro task queue, and the setTimeout goes out of the stack
- Promise pushes, Promise CB1 (the first THEN) goes into the Web APIs and into the microtask queue
- Promise stack, console.log(5) push
- After printing 5, console.log(5) is off the stack
- Finally, the main thread executes, main() exits the stack, the stack is empty. The status is as follows:
- The stack is empty and the microtask queue in the task queue is not empty
- Promise.then 1 push, console.log(3) push, print 3
- Console. log(3), promise. then 1 out of the stack, promise. then 2 pushed
- Promise.then 2 goes into the Web APIs and calls back into the microtask queue
- The microtask queue is not empty
- Promise.then 2 push, console.log(4), print 4
- Console. log(4), promise.then 2
- If the microtask queue is empty, check the macro task queue
- SetTimeout cb into the stack
- Console. log(5) pushes and prints 5
- The console. The log (5) out of the stack
- SetTimeout cb stack
At this point, the stack is empty.
The whole process can be described as follows:
Note that when all synchronous tasks on the main thread are completed, the thread is checked for any microtasks, and if any microtasks are executed, the next macro task is executed after all the current microtasks have been executed.
Macro tasks versus microtasks
- Macro tasks (tasks) : setTimeout setInterval, setImmediate, requestAnimationFrame, I/O, UI Rendering…
- MicroTask: Promise, Process. NextTick (Node only), MutationObserver…
conclusion
- The purpose of JavaScript is that it is single-threaded, but it is also non-blocking because of the event loop.
- The browser provides the JS engine threads to interpret and execute THE JS code, but also provides event-triggered threads, timer triggered threads, and so on (Web APIs). The JS engine maintains a call stack for code execution.
- When the asynchronous task is processed, its callback will be put into the task queue to wait for execution. The task queue is divided into macro task queue and micro task queue. After the current macro task is pushed into the stack, all the microtasks against the current micro task will be executed first, and finally the next macro task will be pushed into the stack, and so on.
- Tasks in the task queue are executed on the stack only after the stack is cleared.
- We can assume that the task queue contains callbacks, network requests, setTimeout, and JS events.
- If there is a computationally complex time-consuming task in the synchronous code, it blocks the execution of the callback function in the asynchronous code.
- On when Web APIs put callbacks in the task queue: when appropriate. Then when the state of the promise changes.
Eventloop in the browser was analyzed above, but Eventloop in the Node environment has its own model, which is not exactly similar to the browser, and there is a chance to explore it again.
Refer to the link
- Detail the Event Loop mechanism in JavaScript
- This time, understand the JavaScript execution mechanism thoroughly
- Figure out the Event Loop in one session (Completely solve this type of interview question)
- In-depth understanding of JavaScript Event loops
- Explore javaScript asynchrony and browser update rendering timing #5 from the Event Loop specification
- JavaScript event loop — video
Tasks, Microtasks, Queues and Schedules