Browser and node event loop

What is an event loop

  • Every browser has at least one event loop, and an event loop has at least one task queue. 循环It means that it is always in an "infinite loop". Continuously push the registered callback function onto the execution stack
  • The browser's event loop standard is specified by the HTML standard, but the event loop in NodeJS is actually slightly different

Why event loop

First, let's look at a simple piece of code:

function a1(){
    
    
            console.log('1')
        }
        function a2(){
    
    
            console.log('2')
        }
        function a3(){
    
    
            console.log('3')
            a1()
            a2()
        }
        a3()

Output:
insert image description here
What is the process of this code being executed?
First of all, if a browser wants to execute a JS script, it needs a "thing" to turn the JS script (essentially a plain text) into a computer instruction that the machine can understand and execute. This "thing" is the JS engine, which actually compiles and executes JS scripts.

The v8 engine has two very core components, 执行栈and . The code being executed is stored in the execution stack, and the value of the variable is stored in the heap, which is usually irregular.

When V8 runs this code, it will be called first a3(). a3()Inside the is called first a1(), followed bya2()

When calling a3 时,第一个帧被创建并压入栈中,帧中包含了a1 的参数和局部变量。 当a3 调用a1 时,第二个帧被创建并被压入栈中,放在第一个帧之上,帧中包含a1 的参数和局部变量。当a1 执行完毕然后返回时,第二个帧就被弹出栈(剩下a3 函数的调用帧 )当a3调用a2时,和第二帧同理,。当a3` is also executed and then returns, the first frame is also popped and the stack is cleared.

DOM and WEB APIs

The js engine can help us execute js scripts, but our goal is to "build a user interface" and the traditional front-end interface is built based on DOM. DOM is a document object model, which provides a series of interfaces that can be directly called by js, except In addition to the DOM interface can be called to js, ​​the browser also provides some WEB API. Regardless of DOM, WEB, or API, they have nothing to do with JS in essence.

V8 is the engine, used to execute JS code, the browser and Node are the execution environment of JS, which provide some APIs that JS can call.

Due to the existence of browsers, JS can now operate DOM and WEB API, and it seems that it can build user interfaces. One thing needs to be made clear in advance, V8 only has stack and heap, and it doesn't know anything about other events such as event loop, DOM, and WEB API. The reason has already been mentioned before, because V8 is only responsible for the compilation and execution of JS code. If you give V8 a piece of JS code, it will execute it from beginning to end without stopping in the middle.

Multi-threaded without async

Under the premise of multiple requests without dependencies, multi-thread synchronization can execute multiple code blocks at the same time. The optimal situation depends on the slowest situation.

Single-threaded asynchronous (event loop)

How does the event loop achieve asynchrony?

We know that there is only one JS thread in the browser, if there is no event loop, it will cause a problem. That is, if JS initiates an asynchronous IO request, the following code will be blocked during the period of time waiting for the result to be returned. We know that the JS main thread and the rendering process are mutually blocked, so this will cause the browser to freeze. how to solve this problem? An effective way is what we will talk about in this section 事件循环.

In fact, 事件循环就是用来做调度的,浏览器和NodeJS中的事件循坏就好像操作系统的调度器一样。the scheduler of the operating system decides when to allocate what resources to whom,

The event loop in browsers and NodeJS is also essentially for scheduling, but the object of scheduling becomes the execution of JS, and the event loop determines when and what code V8 executes (V8 is only responsible for the parsing and execution of JS code, and everything else I don't know). After the event is triggered in the browser or NodeJS, all the work during the time period until the event listener function is executed by V8 is the event loop.

The reason why the event loop can be asynchronous is that when encountering asynchronously executed code "such as setTimeout, setInterval", js calls the browser's WEB API, and at the same time the browser starts timing, when the time is up, or the event is triggered, the corresponding The callback function is put into the queue.

When the main thread executes the program in the call stack "in one breath" and needs to "breathe", the browser will check whether there are "messages" to be processed in the queue. If there is, push the callback function corresponding to the message binding onto the stack.

Microtasks and Macrotasks

micro task micro-task

Microtasks (microtasks) is actually a general term, including two parts:

  • process.nextTick() (node ​​specific) registered callback
  • callbacks registered by promise.then()

macro task macro-task

  • The callback registered by setTimeout
  • The callback registered by setInterval
  • setImmediate (node ​​specific) registered callback
  • Callbacks for I/O registration
  • script (overall code)
  • requestAnimationFrame (browser only)
  • UI rendering (browser only)

The browser's event loop

Browser event loop flow chart:
insert image description here
the specific process of browser EventLoop:

  1. The js engine puts all codes into the execution stack, pops them up and executes them one by one, some of these tasks are synchronous and some are asynchronous (macro tasks or micro tasks).

  2. If a macro task is found when executing the code in the stack, it will be handed over to the corresponding thread of the browser to process, and the browser thread will push the message of the macro task (or called the callback function) at the right time (such as the shortest delay time of the timer) into the macro task queue. The tasks in the macro task queue will only be executed when the execution stack is empty.

  3. If a microtask is found when executing the code in the stack, it will be pushed into the microtask queue. Like the macrotask queue, the tasks in the microtask queue will be executed when the execution stack is empty, but the microtask is always executed before the macrotask.

  4. When the execution stack is empty, eventLoop goes to the microtask queue, pops up the first task in turn and puts it into the execution stack and executes it. If another microtask is generated during execution, it is pushed to the end of the queue, so that the cycle continues until the microtask queue Is empty.

  5. When both the execution stack and the microtask queue are empty, eventLoop transfers to the macrotask queue, and takes out the task at the head of the queue and puts it into the execution stack for execution. It should be noted that only one macro task is executed in each cycle.

  6. Repeat 1-5 process

  7. ...until both the stack and the queue are empty, the code execution ends. The engine sleeps and waits until the next task occurs.

    Notice:

  • Only one macro task is taken at a time, and the micro task is executed immediately after execution.
  • Microtasks are executed sequentially until the microtask queue is empty.

node event loop

Simple schematic diagram of node event flow

insert image description here
insert image description here

Macro tasks in node

  • Timers Queue
  • IO Callbacks Queue
  • Check Queue
  • Close Callbacks Queue

Microtasks in node

  • Next Tick Queue: is the callback task for placing process.nextTick(callback)
  • Other Micro Queue: Place other microtasks, such as Promise, etc.

Macro task queue of nodejs

  • timers phase: the first time you enter the event loop, it will start from the timer phase. This stage will judge whether there is an expired timer callback (including setTimeout and setInterval). If there is, all expired timer callbacks will be executed. After execution, if the corresponding microtask is triggered in the callback, all microtasks will be executed , and then enter the I/O callbacks stage after executing the microtask.
  • I/O callback phase: Execute callbacks other than the callbacks of the close event, callbacks set by timers, and callbacks set by setImmediate().
  • idle, prepare stage: only used internally by node.
  • poll phase: Get new I/O events, and node will block here under appropriate conditions.
  • Check phase: Execute the callbacks set by setImmediate(). (It will check whether there is a callback related to setImmediate. If it exists, execute all callbacks. After execution, if the corresponding microtask is triggered in the callback, it will continue to execute all microtasks. After executing the microtask, it will enter the Close callbacks stage.)
  • close callbacks phase: execute some close callbacks, such as: socket.on('close', ...), etc.

The specific process of Node's EventLoop

  • Execute the synchronous code of the global script
  • Execute microtask microtasks, first execute all tasks in all Next Tick Queue, and then execute all tasks in Other Microtask Queue.
  • Execute macrotask macro tasks, a total of 6 stages, starting from the first stage, and then proceeding to the sixth stage, Node 11 and after, for each stage of the event loop, the execution order of microtasks is unified, in each After the callback is called, the corresponding microtask will be executed instead of waiting until all the callbacks are executed.
  • Repeat 1 - 3 process.

Summary of the event loop

  • The event loop is the core mechanism for browsers and Node to execute JS code, but the implementation mechanisms of the browser and NodeJS event loops are somewhat different.
  • The browser event loop has a macro queue and a micro queue, and the micro queues are executed one by one until the queue is empty during the execution process. The macro queue only takes a task at the head of the queue and puts it into the execution stack for execution. After execution, the micro queue is executed. Queue, and form a loop.
  • In Node 11 and later, for each stage of the event loop, the execution order of microtasks is unified. After each callback is called, the corresponding microtask is executed, and it will not be executed until all callbacks are executed.

Guess you like

Origin blog.csdn.net/weixin_43183219/article/details/124187552