Discover why browsers and Node.js designed EventLoop this way!
This article will let you explore why the browser and Node.js are designing EventLoop in this way. I hope it will be helpful to everyone!
Event Loop is a basic concept of JavaScript. It is a must-ask in interviews and is often talked about in daily life. But have you ever thought about why there is Event Loop and why it is designed like this? Woolen cloth?
Today we will explore the reasons.
The browser's Event Loop
JavaScript is used to implement web page interaction logic, involving dom operations. If multiple threads operate at the same time, synchronization and mutual exclusion are required. The processing is designed to be single-threaded for simplicity. However, if it is single-threaded, it will be blocked when encountering timing logic and network requests. How to do it?
You can add a layer of scheduling logic. Just encapsulate the JS code into tasks and put them in a task queue, and the main thread will continue to fetch tasks and execute them.
Every time a task is executed, a new call stack will be created.
Among them, timers and network requests are actually executed in other threads. After execution, a task is placed in the task queue to tell the main thread to continue. Executed.
Because these asynchronous tasks are executed in other threads, and then notified to the main thread through the task queue, it is an event mechanism, so this loop is called Event Loop.
These asynchronous tasks executed in other threads include timers (setTimeout, setInterval), UI rendering, and network requests (XHR or fetch).
However, the current Event Loop has a serious problem. There is no concept of priority. It is only executed in order. If there are high-priority tasks, they will not be executed in time. Therefore, a queue-jumping mechanism must be designed.
Then just create a high-priority task queue. After each ordinary task is executed, all high-priority tasks are executed, and then the ordinary tasks are executed.
#With the queue jumping mechanism, high-quality tasks can be executed in a timely manner.
This is the current browser Event Loop.
The ordinary tasks are called MacroTask (macro tasks), and the high-quality tasks are called MicroTasks (micro tasks).
Macro tasks include: setTimeout, setInterval, requestAnimationFrame, Ajax, fetch, script tag code.
Microtasks include: Promise.then, MutationObserver, Object.observe.
How to understand the division of macro and micro tasks?
Timers and network requests are common asynchronous logic that notifies the main thread after other threads have finished running, so they are all macro tasks.
The three types of high-quality tasks are also easy to understand. MutationObserver and Object.observe both monitor changes in an object. Changes are very instantaneous. You must respond immediately, otherwise it may change again. Yes, Promise organizes asynchronous processes, and calling then at the asynchronous end is also very good.
This is the design of Event Loop in the browser: The Loop mechanism and Task queue are designed to support asynchronous and solve the problem of logic execution blocking the main thread. The queue jumping mechanism of the MicroTask queue is designed to solve the problem of high The problem of executing optimal tasks as early as possible.
But later, the execution environment of JS was not only a browser, but also Node.js, which also had to solve these problems, but the Event Loop it designed was more detailed.
Event loop of Node.js
Node is a new JS running environment, which also supports asynchronous logic, including timers, IO and network requests, obviously, can also be run using Event Loop.
However, the browser's Event Loop is designed for browsers. For high-performance servers, the design is still a bit rough.
Where is it rough?
The browser's Event Loop is only divided into two levels of priority, one is macro tasks and the other is micro tasks. But there is no further prioritization between macro tasks, and there is no further prioritization between micro tasks.
And Node.js task macro tasks also have priorities. For example, the logic of the timer has a higher priority than the logic of IO, because when it comes to time, the earlier the more accurate it is; and the close resource The priority of processing logic is very low, because if it is not closed, it will occupy more resources such as memory and have little impact.
So the macro task queue was split into five priority levels: Timers, Pending, Poll, Check, and Close.
Explain these five macro tasks:
Timers Callback: When it comes to time, the earlier the execution, the more accurate it will be, so this has the highest priority and is easy to understand.
Pending Callback: Callback when handling network, IO and other exceptions. Some *niux systems will wait for errors to be reported, so they must be handled.
Poll Callback: Processing IO data and network connection, this is what the server mainly handles.
Check Callback: The callback for executing setImmediate. The characteristic is that this can be called back just after the IO is executed.
Close Callback: Callback to close the resource. Delayed execution will not affect it and has the lowest priority.
So, the Event Loop of Node.js runs like this:
There is another difference that you should pay special attention to:
The Event Loop of Node.js is not like the browser that executes one macro task at a time, and then executes all micro tasks. Instead, it executes a certain number of Timers macro tasks, then executes all micro tasks, and then executes a certain amount. number of Pending macro tasks, and then execute all micro tasks. The same is true for the remaining Poll, Check, and Close macro tasks. (Correction: This was the case before node 11. After node 11, it was changed to each macro task executing all micro tasks)
Why is this?
In fact, it is easy to understand according to the priority:
Assume that the priority of the macro task in the browser is 1, so it is executed in order, that is, one macro task, all A microtask, then a macrotask, then all microtasks.
The macro tasks of Node.js also have priorities, so Node.js’s Event Loop will allocate all tasks with the current priority each time. After the macro task is finished, run the micro task, and then run the next priority macro task.
That is, a certain number of Timers macro tasks, then all micro tasks, then a certain number of Pending Callback macro tasks, and then all micro tasks.
Why is it said to be a certain amount?
Because if there are too many macro tasks in a certain stage, the next stage will never be executed, so there is an upper limit, and the remaining next Event Loop will continue to be executed.
In addition to macro tasks having priorities, micro tasks are also prioritized. There is an additional high priority micro task of process.nextTick, which runs before all ordinary micro tasks.
So, the complete process of Node.js Event Loop is like this:
- Timers stage: Execute certain The number of timers, that is, the callbacks of setTimeout and setInterval, if there are too many, leave them for next execution
- Microtasks: execute all nextTick microtasks, and then execute other ordinary microtasks
- Pending phase: Execute a certain number of IO and network exception callbacks. If there are too many, leave them for next execution.
- Microtasks: Execute all nextTick microtasks, and then execute other ordinary microtasks. Task
- Idle/Prepare Phase: A phase used internally
- Microtasks: execute all nextTick microtasks, and then execute other ordinary microtasks
- Poll phase: Execute a certain number of file data callbacks and network connection callbacks. If there are too many, leave them to the next execution. If there is no IO callback and there are no callbacks in the timers and check stages to be processed, just block here and wait for the IO event
- Microtasks: execute all nextTick microtasks, and then execute other ordinary Microtask
- Check Phase: Execute a certain number of setImmediate callbacks. If there are too many, leave them to the next execution.
- Microtasks: Execute all nextTick microtasks, and then execute other ordinary microtasks
- Close phase: Execute a certain number of close event callbacks, if there are too many Save it for next execution.
- Microtasks: Execute all nextTick microtasks, and then execute other ordinary microtasks
Compared with the Event Loop in the browser, it is obviously much more complicated, but after our previous Through the analysis, you can also understand:
Node.js has prioritized macro tasks. From high to low, they are Timers, Pending, Poll, Check, and Close. It also prioritizes micro tasks. The tasks are divided into nextTick microtasks and other microtasks. The execution process is to first execute a certain number of macrotasks of the current priority (leaving the rest for the next cycle), then execute the microtasks of process.nextTick, then execute ordinary microtasks, and then execute a certain number of the next priority. number of macro tasks. . This cycle continues. There is also an Idle/Prepare stage for Node.js internal logic, so you don’t need to worry about it.
Changed the way of executing one macro task at a time in the browser Event Loop, which allows high-priority macro tasks to be executed earlier, but also sets an upper limit to prevent the next stage from not being executed. .
There is another point to pay special attention to, which is the poll stage: If it is executed to the poll stage and it is found that the poll queue is empty and there are no tasks to be executed in the timers queue and check queue, then it will be blocked and so on. Wait for IO events here instead of idling. This design is also because the server mainly handles IO, and blocking here can respond to IO earlier.
The complete Node.js Event Loop is like this:
Compare the browser's Event Loop:
The overall design ideas of the Event Loop of the two JS running environments are similar, except that the Event Loop of Node.js has a more fine-grained division of macro tasks and micro tasks, which is also easy to understand. After all, Node The environment for .js is different from that of browsers. More importantly, the performance requirements of the server will be higher.
Summary
JavaScript was first used to write web page interaction logic. In order to avoid the synchronization problem of multiple threads modifying the DOM at the same time, it was designed to be single-threaded. To solve the single-thread blocking problem, a layer of scheduling logic is added, that is, Loop loop and Task queue, and the blocking logic is placed in other threads to run, thus supporting asynchronous operation. Then in order to support high-priority task scheduling, micro-task queues were introduced. This is the browser's Event Loop mechanism: execute one macro task at a time, and then execute all micro tasks.
Node.js is also a JS running environment. If you want to support asynchronous, you also need to use Event Loop. However, the server environment is more complex and has higher performance requirements, so Node.js has both macro and micro tasks. Made a more fine-grained priority classification:
Node.js is divided into 5 types of macro tasks, namely Timers, Pending, Poll, Check, and Close. Two types of microtasks are divided, namely process.nextTick microtasks and other microtasks.
The Event Loop process of Node.js is to execute a certain number of macro tasks in the current stage (the rest will be executed in the next loop), and then execute all micro tasks. There are Timers, Pending, Idle/ Prepare, Poll, Check, Close 6 stages. (Correction: This was the case before node 11. After node 11, it was changed to each macro task to execute all micro tasks)
The Idle/Prepare stage is used internally by Node.js, so don’t worry about it.
Special attention should be paid to the Poll stage. If the poll queue is empty and the timers and check queues are also empty, it will be blocked here waiting for IO until there is a callback in the timers and check queues. Continue the loop again.
Event Loop is a set of scheduling logic designed by JS to support asynchronous and task priority. It has different designs for different environments such as browsers and Node.js (mainly the division of task priorities) (different granularity), Node.js faces more complex environments and has higher performance requirements, so the Event Loop design is more complex.
For more node-related knowledge, please visit: nodejs tutorial! !
The above is the detailed content of Discover why browsers and Node.js designed EventLoop this way!. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

When developing websites using CraftCMS, you often encounter resource file caching problems, especially when you frequently update CSS and JavaScript files, old versions of files may still be cached by the browser, causing users to not see the latest changes in time. This problem not only affects the user experience, but also increases the difficulty of development and debugging. Recently, I encountered similar troubles in my project, and after some exploration, I found the plugin wiejeben/craft-laravel-mix, which perfectly solved my caching problem.

The Installation, Configuration and Optimization Guide for HDFS File System under CentOS System This article will guide you how to install, configure and optimize Hadoop Distributed File System (HDFS) on CentOS System. HDFS installation and configuration Java environment installation: First, make sure that the appropriate Java environment is installed. Edit /etc/profile file, add the following, and replace /usr/lib/java-1.8.0/jdk1.8.0_144 with your actual Java installation path: exportJAVA_HOME=/usr/lib/java-1.8.0/jdk1.8.0_144exportPATH=$J

In the process of developing a website, improving page loading has always been one of my top priorities. Once, I tried using the Miniify library to compress and merge CSS and JavaScript files in order to improve the performance of the website. However, I encountered many problems and challenges during use, which eventually made me realize that Miniify may no longer be the best choice. Below I will share my experience and how to install and use Minify through Composer.

There are many ways to monitor the status of HDFS (Hadoop Distributed File System) on CentOS systems. This article will introduce several commonly used methods to help you choose the most suitable solution. 1. Use Hadoop’s own WebUI, Hadoop’s own Web interface to provide cluster status monitoring function. Steps: Make sure the Hadoop cluster is up and running. Access the WebUI: Enter http://:50070 (Hadoop2.x) or http://:9870 (Hadoop3.x) in your browser. The default username and password are usually hdfs/hdfs. 2. Command line tool monitoring Hadoop provides a series of command line tools to facilitate monitoring

Troubleshooting HDFS configuration errors under CentOS Systems This article is intended to help you solve problems encountered when configuring HDFS in CentOS systems. Please follow the following steps to troubleshoot: Java environment verification: Confirm that the JAVA_HOME environment variable is set correctly. Add the following in the /etc/profile or ~/.bashrc file: exportJAVA_HOME=/path/to/your/javaexportPATH=$JAVA_HOME/bin: $PATHExecute source/etc/profile or source~/.bashrc to make the configuration take effect. Hadoop

I encountered a tricky problem when developing a multi-device-compatible website: how to accurately identify the user's browser and device information. After trying multiple methods, I found that directly parsing user-agent strings (User-Agent) are both complex and unreliable, and often misjudgments occur. Fortunately, I successfully solved this problem by installing the WhichBrowser/Parser library using Composer.

The browser's unresponsive method after the WebSocket server returns 401. When using Netty to develop a WebSocket server, you often encounter the need to verify the token. �...

Discussion on the reasons why JavaScript cannot obtain user computer hardware information In daily programming, many developers will be curious about why JavaScript cannot be directly obtained...
