JS Study Notes - In-depth understanding of macro tasks, micro tasks, and event loops in browsers and Node.js

JavaScript is single-threaded

JavaScript is a single-threaded scripting language, that is, JS code can only run in one process. In other words, JS can only execute one task at the same time. But if all the codes are executed synchronously, this will cause serious problems. For example, if we want to get some data from the remote end, should we keep looping the code to judge whether the returned result has been obtained?

So there is the concept of asynchronous events, registering a callback function, such as sending a network request, we tell the main program to notify me after receiving the data, and then we can do other things.

Then after the asynchronous completion, we will be notified, but the program may be doing other things at this time, so even if the asynchronous completion needs to wait, wait until the program is free to have time to see which asynchronous has been completed, you can go to implement.

Introduction to Browser Threads

GUI rendering thread

Responsible for rendering browser interface HTML elements

JS engine thread

Responsible for processing the JavaScript script main program

timer trigger thread

Timer setIntervaland setTimeoutits thread

browser event thread

Used to control events, such as triggered onload, click events, etc.

http request thread

After XMLHttpRequestconnecting, a new thread request is opened through the browser. When a state change is detected, if a callback function is set, the asynchronous thread will generate a state change event and put it in the task queue of the JavaScript engine for processing .

Macrotasks and Microtasks

What are macro tasks and micro tasks?

macro task

  • setTimeout
  • setInterval
  • setImmediate(Node.js)
  • requestAnimationFrame(browser)
  • UI Rendering(browser)
  • I/O
  • script

micro task

  • Promise.then() Promise.catch() Promise.finally()
  • MutationObserver
  • Object.observe
  • async await
  • process.nextTick(Node)

The browser's event loop

Created with Raphaël 2.3.0 任务进入执行栈 是否为同步任务 主线程 任务全部执行完毕 读取任务队列中的结果,进入主线程执行 Event Table Event Queue yes no

Synchronous and asynchronous tasks enter different execution "places", synchronously enter the main thread, and asynchronously enter the Event Table and register functions. When the specified thing is completed, Event Table will move this function into the task queue (Event Queue). When the task in the main thread is empty after execution, go to the task queue (Event Queue) to read the corresponding function and enter the main thread for execution.

The browser's macro task and micro task mechanism

Created with Raphaël 2.3.0 将宏任务放入宏任务队列 是否存在微任务 将微任务放入微任务队列 宏任务执行结束 是否存在可执行的微任务 执行所有微任务并执行下一个宏任务 yes no yes

JS asynchrony also has a mechanism, that is, when encountering a macro task, execute the macro task first, put the macro task into the task queue (event queue), and then execute the micro task, put the micro task into the micro task queue (micro task queue), However, these two queues are not a queue

order of execution

Main thread >> microtasks created on main thread >> macrotasks created on main thread >> main thread >> microtasks created on main thread >> macrotasks created on main thread...

example

console.log(1)
setTimeout(()=>{
    
    
    console.log(2)
},0)
new Promise((resolve,reject)=>{
    
    
    console.log(3)
    resolve()
}).then(res=>{
    
    
    console.log(4)
})
console.log(5)
setTimeout(()=>{
    
    
    new Promise((resolve,reject)=>{
    
    
        console.log(6)
    }).then(res=>{
    
    
        console.log(7)
    })
},0)
console.log(8)

/*
控制台输出:
1
3
5
8
4
2
6

/// 7不输出因为该Promise状态仍为pending,且无法变为resolved
*/

The event loop mechanism of Node.js

Description of each stage of Event Loop

stage describe
timers Callback function for processing setTimeoutandsetInterval
pending callbacks Callbacks to perform certain system operations
idle,prepare Used internally by Node, ignored
poll Wait for new I/O events to trigger, and execute I/O-related callbacks
check When the execution of the poll phase is completed, it will enter the execution of the check phase, and the execution content of this phase is all setImmediatecallbacks
close callbacks When the socket is closed abnormally, closethe event callback will be executed at this stage

Macrotask and microtask queues in Node

macro task queue

  • timers queue
  • pending callbacks queue
  • check queue
  • close queue

microtask queue

  • next Tick Queue
  • other Micro Queue

poll polling phase

Poll is a core stage, waiting for the triggering of new I/O events, and executing I/O-related callbacks

The main function:

  • 执行到期的setTimeoutsetInterval的回调函数
  • 处理poll队列中的事件

工作机制:当没有timers被调度,分两种情况:

  1. 如果poll队列不为空,会挨个执行队列里的callback,直到队列为空,或达到系统限制
  2. 如果poll队列为空,分两种情况:
    • 如果执行了setImmediateeventLoop会结束poll阶段,进入到check阶段执行
    • 如果没有执行setImmediateeventLoop会等待callback进入队列

一旦poll队列为空,evetloop会检查timers,如果计时已到,event loop 会回到 timers 阶段,执行相应的回调函数.

执行顺序

  • timers
  • nextTickQueue
  • otherMicroQueue
  • pending callbacks
  • nextTickQueue
  • otherMicroQueue
  • idle,prepare
  • nextTickQueue
  • otherMicroQueue
  • poll(可能返回到timers阶段)
  • nextTickQueue
  • otherMicroQueue
  • check
  • nextTickQueue
  • otherMicroQueue
  • close callbacks

示例

console.log(0);

setTimeout(() => {
    
    
  console.log(1);
  setTimeout(() => {
    
    
    console.log(2);
  }, 0);
  setImmediate(() => {
    
    
    console.log(3);
  })
  process.nextTick(() => {
    
    
    console.log(4);  
  })
}, 0);

setImmediate(() => {
    
    
  console.log(5);
  process.nextTick(() => {
    
    
    console.log(6);  
  })
})

setTimeout(() => {
    
              
  console.log(7);
  process.nextTick(() => {
    
    
    console.log(8);   
  })
}, 0);

process.nextTick(() => {
    
    
  console.log(9);  
})

console.log(10);
/* Node.js 控制台输出:
0
10
9
1
4
7
8
5
6
3
2
*/

Guess you like

Origin blog.csdn.net/m0_52761633/article/details/120693993