search
HomeWeb Front-endJS TutorialAnalyzing the event loop mechanism of Node.js

Analyzing the event loop mechanism of Node.js

Oct 20, 2018 pm 04:25 PM
es6javascriptnode.js

The content of this article is about analyzing the event loop mechanism of Node.js. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.

The event loop mechanism and some related concepts have been introduced in detail in the browser article, but it is mainly for research on the browser side. Is the same for the Node environment? Let’s take a look at a demo first:

setTimeout(()=>{
    console.log('timer1')
    Promise.resolve().then(function() {
        console.log('promise1')
    })}, 0)setTimeout(()=>{
    console.log('timer2')
    Promise.resolve().then(function() {
        console.log('promise2')
    })}, 0)

Compile and run it with the naked eye. The result in the browser is as follows. You already know the truth, so I won’t go into details here.

timer1
promise1
timer2
promise2

Then execute it under Node, eh. . . Strange, the running result is different from the browser~

timer1
timer2
promise1
promise2

The example shows that the event loop mechanism of the browser and Node.js is different, let’s take a look~

Event processing of Node.js

Node.js uses V8 as the parsing engine of js, and uses its own designed libuv for I/O processing. libuv is an event-driven cross-platform abstraction layer that encapsulates Some underlying features of different operating systems provide a unified API to the outside world. The event loop mechanism is also implemented in it. Core source code reference:

int uv_run(uv_loop_t* loop, uv_run_mode mode) {
  int timeout;
  int r;
  int ran_pending;
  r = uv__loop_alive(loop);
  if (!r)
    uv__update_time(loop);
  while (r != 0 && loop->stop_flag == 0) {
    uv__update_time(loop);
    // timers阶段
    uv__run_timers(loop);
    // I/O callbacks阶段
    ran_pending = uv__run_pending(loop);
    // idle阶段
    uv__run_idle(loop);
    // prepare阶段
    uv__run_prepare(loop);
    timeout = 0;
    if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT)
      timeout = uv_backend_timeout(loop);
    // poll阶段
    uv__io_poll(loop, timeout);
    // check阶段
    uv__run_check(loop);
    // close callbacks阶段
    uv__run_closing_handles(loop);
    if (mode == UV_RUN_ONCE) {
      uv__update_time(loop);
      uv__run_timers(loop);
    }
    r = uv__loop_alive(loop);
    if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT)
      break;
  }
  if (loop->stop_flag != 0)
    loop->stop_flag = 0;
  return r;
}

According to the official introduction of Node.js, each event loop contains 6 stages. , corresponding to the implementation in the libuv source code, as shown in the figure below

Analyzing the event loop mechanism of Node.js

timers stage: This stage executes the callback of timer (setTimeout, setInterval)

I/ O callbacks phase: Execute some system call errors, such as network communication error callback

idle, prepare phase: Only used internally by node

poll phase: Get new I/O events, appropriate Under the conditions, the node will be blocked here

check stage: execute the callback of setImmediate()

close callbacks stage: execute the close event callback of the socket

We focus on timers and poll , Just check these three stages, because most asynchronous tasks in daily development are processed in these three stages.

timers phase

timers is the first phase of the event loop, Node Will check whether there is an expired timer, and if so, push its callback into the timer's task queue to wait for execution. In fact, Node There is no guarantee that the timer will be executed immediately when the preset time is reached, because Node's expiration check of the timer is not necessarily reliable. It will be affected by other running programs on the machine, or the main thread is not idle at that time. For example, in the following code, the execution order of setTimeout() and setImmediate() is uncertain.

setTimeout(() => {
  console.log('timeout')
  }, 0)
  setImmediate(() => {
  console.log('immediate')
  })

But if you put them in an I/O callback, setImmediate() must be executed first, because the poll phase is followed by the check phase.

poll phase

The poll phase mainly has two functions:

Processing events in the poll queue

When there is a timer that has timed out, execute its callback Function

even loop will synchronously execute the callbacks in the poll queue until the queue is empty or the executed callbacks reach the system upper limit (the upper limit is unknown), then the even loop will check whether there is a preset setImmediate( ), divided into two situations:

If there is a preset setImmediate(), the event loop will end the poll phase and enter the check phase, and execute the task queue of the check phase

If there is no preset setImmediate(), the event loop will block and wait at this stage

Note one detail, no setImmediate() will cause an event The loop is blocked in the poll phase, so wouldn't the previously set timer not be able to be executed? So, in the poll phase event The loop will have a checking mechanism to check whether the timer queue is empty. If the timer queue is not empty, the event loop starts the next round of event loop, that is, re-enters the timer phase.

check phase

The callback of setImmediate() will be added to the check queue. From the event loop phase diagram, we can know that the execution order of the check phase is after the poll phase.

Summary

Each stage of the event loop has a task queue

When the event loop reaches a certain stage, the task queue of that stage will be executed until the queue is cleared. Or the executed callback reaches the system upper limit before it will move to the next stage

When all stages are executed sequentially once, the event loop is said to have completed a tick

It makes sense. But without the demo, I still don’t understand it completely. I’m anxious, now!

const fs = require('fs')fs.readFile('test.txt', () => {
  console.log('readFile')
  setTimeout(() => {
    console.log('timeout')
  }, 0)
  setImmediate(() => {
    console.log('immediate')
  })
  })

There should be no doubt about the execution results

readFile
immediate
timeout

Differences between Node.js and the browser’s Event Loop

Recall the previous article, microtask tasks in the browser environment The queue is executed after each macrotask is executed.

Analyzing the event loop mechanism of Node.js

In Node.js, microtask will be executed between various stages of the event loop. That is, after a stage is executed, the tasks in the microtask queue will be executed.

Analyzing the event loop mechanism of Node.js

demo review

Review the demo at the beginning of the article, the global script (main()) is executed, and the two timers are sequentially Put it into the timer queue, main() is executed, the call stack is idle, and the task queue starts executing;

Analyzing the event loop mechanism of Node.js

首先进入timers阶段,执行timer1的回调函数,打印timer1,并将promise1.then回调放入microtask队列,同样的步骤执行timer2,打印timer2;

至此,timer阶段执行结束,event loop进入下一个阶段之前,执行microtask队列的所有任务,依次打印promise1、promise2。

对比浏览器端的处理过程:

Analyzing the event loop mechanism of Node.js

process.nextTick() VS setImmediate()

In essence, the names should be swapped. process.nextTick() fires more immediately than setImmediate()

来自官方文档有意思的一句话,从语义角度看,setImmediate() 应该比 process.nextTick() 先执行才对,而事实相反,命名是历史原因也很难再变。

process.nextTick() 会在各个事件阶段之间执行,一旦执行,要直到nextTick队列被清空,才会进入到下一个事件阶段,所以如果递归调用 process.nextTick(),会导致出现I/O starving(饥饿)的问题,比如下面例子的readFile已经完成,但它的回调一直无法执行:

const fs = require('fs')const starttime = Date.now()let endtime
fs.readFile('text.txt', () => {
  endtime = Date.now()
  console.log('finish reading time: ', endtime - starttime)})let index = 0function handler () {
  if (index++ >= 1000) return
  console.log(`nextTick ${index}`)
  process.nextTick(handler)
  // console.log(`setImmediate ${index}`)
  // setImmediate(handler)}handler()

process.nextTick()的运行结果:

nextTick 1
nextTick 2
......
nextTick 999
nextTick 1000
finish reading time: 170

替换成setImmediate(),运行结果:

setImmediate 1
setImmediate 2
finish reading time: 80
......
setImmediate 999
setImmediate 1000

这是因为嵌套调用的 setImmediate() 回调,被排到了下一次event loop才执行,所以不会出现阻塞。

总结

1、Node.js 的事件循环分为6个阶段

2、浏览器和Node 环境下,microtask 任务队列的执行时机不同

Node.js中,microtask 在事件循环的各个阶段之间执行

浏览器端,microtask 在事件循环的 macrotask 执行完之后执行

3、递归的调用process.nextTick()会导致I/O starving,官方推荐使用setImmediate()

The above is the detailed content of Analyzing the event loop mechanism of Node.js. For more information, please follow other related articles on the PHP Chinese website!

Statement
This article is reproduced at:github. If there is any infringement, please contact admin@php.cn delete
Python and JavaScript: Understanding the Strengths of EachPython and JavaScript: Understanding the Strengths of EachMay 06, 2025 am 12:15 AM

Python and JavaScript each have their own advantages, and the choice depends on project needs and personal preferences. 1. Python is easy to learn, with concise syntax, suitable for data science and back-end development, but has a slow execution speed. 2. JavaScript is everywhere in front-end development and has strong asynchronous programming capabilities. Node.js makes it suitable for full-stack development, but the syntax may be complex and error-prone.

JavaScript's Core: Is It Built on C or C  ?JavaScript's Core: Is It Built on C or C ?May 05, 2025 am 12:07 AM

JavaScriptisnotbuiltonCorC ;it'saninterpretedlanguagethatrunsonenginesoftenwritteninC .1)JavaScriptwasdesignedasalightweight,interpretedlanguageforwebbrowsers.2)EnginesevolvedfromsimpleinterpreterstoJITcompilers,typicallyinC ,improvingperformance.

JavaScript Applications: From Front-End to Back-EndJavaScript Applications: From Front-End to Back-EndMay 04, 2025 am 12:12 AM

JavaScript can be used for front-end and back-end development. The front-end enhances the user experience through DOM operations, and the back-end handles server tasks through Node.js. 1. Front-end example: Change the content of the web page text. 2. Backend example: Create a Node.js server.

Python vs. JavaScript: Which Language Should You Learn?Python vs. JavaScript: Which Language Should You Learn?May 03, 2025 am 12:10 AM

Choosing Python or JavaScript should be based on career development, learning curve and ecosystem: 1) Career development: Python is suitable for data science and back-end development, while JavaScript is suitable for front-end and full-stack development. 2) Learning curve: Python syntax is concise and suitable for beginners; JavaScript syntax is flexible. 3) Ecosystem: Python has rich scientific computing libraries, and JavaScript has a powerful front-end framework.

JavaScript Frameworks: Powering Modern Web DevelopmentJavaScript Frameworks: Powering Modern Web DevelopmentMay 02, 2025 am 12:04 AM

The power of the JavaScript framework lies in simplifying development, improving user experience and application performance. When choosing a framework, consider: 1. Project size and complexity, 2. Team experience, 3. Ecosystem and community support.

The Relationship Between JavaScript, C  , and BrowsersThe Relationship Between JavaScript, C , and BrowsersMay 01, 2025 am 12:06 AM

Introduction I know you may find it strange, what exactly does JavaScript, C and browser have to do? They seem to be unrelated, but in fact, they play a very important role in modern web development. Today we will discuss the close connection between these three. Through this article, you will learn how JavaScript runs in the browser, the role of C in the browser engine, and how they work together to drive rendering and interaction of web pages. We all know the relationship between JavaScript and browser. JavaScript is the core language of front-end development. It runs directly in the browser, making web pages vivid and interesting. Have you ever wondered why JavaScr

Node.js Streams with TypeScriptNode.js Streams with TypeScriptApr 30, 2025 am 08:22 AM

Node.js excels at efficient I/O, largely thanks to streams. Streams process data incrementally, avoiding memory overload—ideal for large files, network tasks, and real-time applications. Combining streams with TypeScript's type safety creates a powe

Python vs. JavaScript: Performance and Efficiency ConsiderationsPython vs. JavaScript: Performance and Efficiency ConsiderationsApr 30, 2025 am 12:08 AM

The differences in performance and efficiency between Python and JavaScript are mainly reflected in: 1) As an interpreted language, Python runs slowly but has high development efficiency and is suitable for rapid prototype development; 2) JavaScript is limited to single thread in the browser, but multi-threading and asynchronous I/O can be used to improve performance in Node.js, and both have advantages in actual projects.

See all articles

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

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

Hot Tools

mPDF

mPDF

mPDF is a PHP library that can generate PDF files from UTF-8 encoded HTML. The original author, Ian Back, wrote mPDF to output PDF files "on the fly" from his website and handle different languages. It is slower than original scripts like HTML2FPDF and produces larger files when using Unicode fonts, but supports CSS styles etc. and has a lot of enhancements. Supports almost all languages, including RTL (Arabic and Hebrew) and CJK (Chinese, Japanese and Korean). Supports nested block-level elements (such as P, DIV),

SublimeText3 Linux new version

SublimeText3 Linux new version

SublimeText3 Linux latest version

Dreamweaver Mac version

Dreamweaver Mac version

Visual web development tools

MantisBT

MantisBT

Mantis is an easy-to-deploy web-based defect tracking tool designed to aid in product defect tracking. It requires PHP, MySQL and a web server. Check out our demo and hosting services.

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor