JS single-threaded
Let’s talk about single threading in JS. Single threading means that all tasks need to be queued until the previous task is finished before the next task is executed. If the first task takes a long time, the second will have to wait.
That how to solve this problem, the browser platform, the underlying browser opens the multi-thread to perform some task, the formation of the asynchronous task which we used to say, for example setTimeout timer, asynchronous tasks can well solve the problem of code blocks, but it also results in code execution order not as straightforward as synchronization task, This is the focus of this article.
JS runtime mechanism
The entire script is initially executed as a macro task. In the execution process, the synchronous code is executed directly. After the macro task waits for the time or succeeds, the callback of the method is put into the macro task queue, and the micro task enters the micro task queue.
The macro task of the current main thread has been dequeued. Check and clear the microtask queue. Next, render the browser UI thread, check the Web worker task, and execute it.
Then take out a macro task to execute. And so on…
EventLoop is a cyclic mechanism that continuously polls a number of queues to find an execution model in which tasks need to be performed and executed in sequence.
Macro tasks versus microtasks
Macro tasks can be understood to mean that the code executed on each execution stack is a macro task (including getting an event callback from the event queue and putting it on the execution stack each time).
The browser will render the page after the execution of one macro task and before the execution of the next macro task in order to enable the execution of JS internal macro tasks and DOM operations in an ordered way.
Macro tasks include script(overall code), setTimeout, setInterval, I/O, UI interaction event, and MessageChannel.
Microtasks can be understood as tasks that need to be executed immediately after the current task is completed. That is, after the current task, but before rendering, perform the empty microtask.
So it’s more responsive than macro tasks because there’s no waiting for UI rendering.
Microtasks include promise.then, MutaionObserver, process. NextTick (node.js environment), and so on.
Code sample
console.log('start')
setTimeout(() = > {
console.log('s1')
Promise.resolve().then(() = > {
console.log('p2')})Promise.resolve().then(() = > {
console.log('p3')})})Promise.resolve().then(() = > {
console.log('p1')
setTimeout(() = > {
console.log('s2')})setTimeout(() = > {
console.log('s3')})})console.log('end')
Copy the code
The code analysisEventLoop
- The first encounter
console.log('start')
And the outputstart
Go ahead. - encounter
setTimeout
Because ofsetTimeout
It’s a macro task. When it’s time, put it in the macro task queue and continue executing. - encounter
Promise.then
Because the current task is a microtask, put it into the microtask queue and continue to execute. - encounter
console.log('end')
And the outputend
. - At this point, all tasks in the current main thread have been executed,
EventLoop
Start to work, find the task that needs to be executed and push it into the execution stack, the microtask takes precedence over the macro task, so firstPromise.resolve().then
Push to the execution stack to continue execution. - encounter
console.log('p1')
And the outputp1
Go ahead. - Meet two
setTimeout
s2
.s3
, and put it into the macro task queue for execution. - At this point, all tasks in the current main thread are completed, the microtask queue is checked and cleared, since there is no microtask at this time, and the macro task from step 2 is retrieved
setTimeout
Start execution. - The output
s1
“And then againp2
,p3
Two microtasks, put them in the microtask queue. - At this point, all tasks in the current main thread are completed, and the microtask queue is checked and cleared. So successive output
p2
,p3
. - At this point, all the tasks in the current main thread are completed, the microtask queue is checked and cleared, since there are no microtasks at this point, and then the macro task from step 7 is fetched
setTimeout
Start execution. So successive outputs2
,s3
. - The entire JS code has been completed, the final output sequence
start
.end
.p1
.s1
.p2
,p3
.s2
.s3
.