node. js Event Loop

Source: Internet
Author: User
Tags emit event listener readfile

Original: Https://github.com/nodejs/node/blob/master/doc/topics/event-loop-timers-and-nexttick.md What is event loopThe event Loop enables node. js to perform non-blocking I/O operations-although JavaScript is actually single-threaded-by handing the operation to the operating system kernel where possible. Since most modern system cores are multithreaded, the kernel can handle multiple operations performed in the background. When one of the operations is completed, the kernel tells node. js that the corresponding callback is added to the polling queue (poll. NET queue) and is eventually executed. More details will be explained later in this topic. Event Loopsnode. JS initializes the event loop at the beginning, processes the target script, and the script may make asynchronous API calls, timed tasks, or Process.nexttick (), and then start the event loop. The following table briefly describes the sequence of operations for the event loop. ┌───────────────────────┐
┌─>│timers│
│└──────────┬────────────┘
│┌──────────┴────────────┐
││I/O callbacks│
│└──────────┬────────────┘
│┌──────────┴────────────┐
││idle, prepare│
│└──────────┬────────────┘┌───────────────┐
│┌──────────┴────────────┐│incoming:│
││poll│<────┤connections,│
│└──────────┬────────────┘│data, etc. │
│┌──────────┴────────────┐└───────────────┘
││check│
│└──────────┬────────────┘
│┌──────────┴────────────┐
└──┤close callbacks│
└────────────────────── ——————— ─┘ Note: Each box represents a stage in the event loop. Each phase has a first in, first Out (FIFO) queue of callback functions that need to be executed. At the same time, each stage is special, basically, when the event loop is carried out to a certain stage, the action that is specific to that stage is performed, and then the callbacks in that stage queue are executed until the queue is empty or the number of execution limits is reached. At this point, the event loop goes to the next stage and repeats itself. Because these operations can result in more scheduled task operations, and new events that are processed by the polling phase are added to the kernel's queue, a new polling event is added when the polling event is processed. Therefore, a long callback task causes the polling phase to exceed the timer threshold. See the timer (timers) and polling (poll) section for details. Note: Windows and Unix/linux implementations are slightly contradictory, but do not affect the description just now. The most important parts are there. There are actually seven or eight stages, but what we're concerned about--what node. js actually uses--is the above. Stage Overview (Phases overview)
    • Timer (Timers): This stage performs callbacks for SetTimeout () and setinterval () plans;
    • I/O callback: Performs almost all of the exception's close callbacks, scheduled callbacks by Timers and Setimmediate ();
    • Idle, Preparation (Idle,prepare): internal use only;
    • Poll (poll): Gets the new I/O event; Nodejs will then properly block;
    • Check: Call the callback of Setimmediate ();
    • Close callbacks: For example Socket.on (' Close ', ...);
Between the event loop runs, node. JS checks for an asynchronous I/O or timer that is waiting, and if not, clears and ends. Stage Details Timers (Timers)The purpose of the timer is to have the specified callback function be executed after a certain threshold value, and the execution time is not necessarily the exact threshold. The callback of the timer will be executed as soon as possible after the established time, however, the execution of the callback may be delayed by the operation of the operating system's schedule or other callbacks. Note: From a technical point of view, the polling stage controls the timing of the timer execution. For example, you set an operation to take after 100ms, and then the script starts to perform a file read operation that requires 95MS:
var fs = require (' FS '); function Someasyncoperation (callback) {  //Assume this takes 95ms to complete  FS.R Eadfile ('/path/to/file ', callback);} var timeoutscheduled = Date.now (); SetTimeout (function () {  var delay = Date.now ()- timeoutscheduled; con Sole.log (Delay + "Ms has passed since I was scheduled");//Do someasyncoperation which takes-MS to C Ompletesomeasyncoperation (function () {var startcallback = Date.now ();//do something that would take 10ms ... while (Date.now ()-Startcallback <) {;//Do Nothing }});         

When the event loops into the polling phase, the queue is empty (Fs.readfile () is not finished), so time continues to elapse knowing that the fastest timer needs to be executed. After 95ms, Fs.readfile () reads the file, its callback is added to the polling queue, and the callback needs to execute 10ms. When this callback is completed, there is no callback in the queue, and the event loop sees the most recent timer and then goes back to the timer stage (timers phase) to perform the previous timer callback. In this example, it is 105ms from the definition of the timer to the middle of the callback execution. Note: To prevent the polling phase from being too long, LIBUV sets a polling limit based on the operating system's differences. I/O callbacksThis phase performs some callbacks for system operations such as TCP errors. For example, if a TCP socket receives a econnrefused error while trying to connect, some *nix systems will wait to report the error. This will be queued to this stage. Polling (poll)The polling phase has two main functions: 1, executes the timer script that has been reached, and then 2, processes the events in the polling queue. When the event loop enters the polling phase and no timer is found:
    • If the polling queue is not empty, the event loop iterates through the callback queue and executes the callback synchronously until the queue is empty or the upper limit is reached (the upper limit, as previously stated, is based on the operating system).
    • If the polling queue is empty:
      • If a callback is defined by Setimmediate (), then the event loop terminates the polling phase and enters the inspection phase to execute the timer callback;
      • If there is no setimmediate (), the event callback waits for the callback to be queued and executes immediately.
Once the polling queue is empty, the event loop looks for timers that are already there. If found, the event loop goes back to the timer stage to execute the callback. Inspection (check)This phase allows the callback function to execute immediately after the polling phase is complete. If the polling phase is idle and a callback has been queued by setimmediate (), the event loop goes into the check phase instead of waiting in the polling phase. Setimmediate () is a special timer that runs in a separate phase in the event loop. It uses the LIBUV API to make the callback function execute after the polling phase is complete. Basically, as the code executes, the event loop eventually enters the polling phase of the wait state, possibly waiting for a connection, a request, and so on. However, if there is a setimmediate () setting a callback and the polling phase is idle, the event loop goes into the check phase instead of waiting for the polling event. ----this rol. closing the callback for the event (close callbacks)If a socket or handle (handle) is abruptly closed (is closed abruptly), such as Socket.destroy (), the ' close ' event is emitted to this stage. Otherwise such events will be emitted through Process.nexttick (). setimmediate () vs setTimeout ()These two are similar, but the difference in the chances of a call can cause them to behave differently.
    • Setimmediate () is designed to execute a callback function once the polling phase is complete;
    • SetTimeout () plans to execute a callback function after a certain time value;
The order of the two executions will vary depending on the context in which they were invoked. If they are called in the main module, they will be affected by the performance of the process (other programs running on this computer will affect them). For example, if we run the following script in a non-I/O loop (that is, in the main module), the order of the two is not fixed because it is affected by the performance of the process:
Timeout_vs_immediate.jssettimeout (function timeout () {  console.log (' timeout ');},0); Setimmediate ( function Immediate () {  console.log (' immediate ');});   

$ node Timeout_vs_immediate.jstimeoutimmediate
$ node Timeout_vs_immediate.jsimmediatetimeout But if you put them in the I/O loop, the callback for Setimmediate () always executes first:
Timeout_vs_immediate.jsvar fs = require (' FS ')Fs.readfile (__filename, () = {  setTimeout () = {    console.log (' timeout ')  }, 0)  setimmediate (() = {console.log (' immediate ') })})

$ node Timeout_vs_immediate.jsimmediatetimeout
The $ node Timeout_vs_immediate.jsimmediatetimeout setimmediate () advantage over SetTimeout () is where setimmediate () is always preceded by any timer in the I/O loop, Regardless of how many timers have been defined. Process.nexttick () Understanding Process.nexttick ()You may have noticed that process.nexttick () does not appear in the table above, although it is indeed an asynchronous API. This is because it is technically not part of the event loop. However, Nexttickqueue will be processed at the end of the current operation, regardless of the stage of the event loop. Looking back at the previous table, you call it at any point in the stage, and all of its callback functions are processed before the event loop continues. Sometimes this can lead to worse situations because it allows you to "block" I/O in a recursive way, which prevents the event loop from entering the polling phase. Why should we allow this ?This is partly because of the design philosophy of node. JS: The API should always be asynchronous, even if it doesn't need to be. Blablabla, I am a bit embarrassed to see the next few paragraphs + dizzy. Embarrassed and dizzy is that these paragraphs are a bit verbose, and the example is not appropriate. The examples are either synchronous, not asynchronous. Either the notation in the example can be avoided, such as the "Connect" event listener should be added first. The Connect () operation, or the variable declaration is best placed before the variable is used, you can avoid the variable advance declaration and the trouble of assigning the value at that time. Did I not understand the secret inside? Process.nexttick () vs setTimeout ()The two functions are somewhat similar but the names are confusing:
    • Process.netxttick () takes effect immediately at the current stage of the event loop;
    • Setimmediate () is the next tick in the next iteration or event loop;
In essence, their names should be exchanged. Process.nexttick () executes more "immediately" than Setimmediate (), but this is a historical issue that cannot be changed. If you change it, the big pile of packages on NPM will be hung up. We recommend that developers use Setimmediate () in all cases because it is more obvious (reason about) and also more compatible, such as the browser side. why use Process.nexttick ()There are two main reasons:
    1. Allow users to handle errors, clean up unwanted resources, or try to send requests again before the end of the event loop;
    2. The callback function must be executed after the call stack has been cleared (unwound) and the event loop continues;
The following two examples are similar, that is, in the line1 distribution of events, but only in the line2 to add monitoring, so the listener callback is not possible to be executed. You can then use Process.nexttick () to enable the current call stack to execute first, that is, to perform line2 registration event monitoring, and then distribute the event in Nexttick.
Const Eventemitter = require (' Events '); const UTIL = require (' util '); function Myemitter () {  Eventemitter.call (this);  Use Nexttick to emit the event once a handler is assigned  Process.nexttick (function () {    this.emit (' event ') c9>); }.bind (this));} Util.inherits (Myemitter, eventemitter); const Myemitter = new myemitter (); Myemitter.on (' event ', function() { Console.log (' an event occurred! ' );});

Translation Summary:This article is not too concise to write, may also be in order to have more audiences, I feel rol more, a meaning to say several times. From the point of view of programming applications, there are approximately seven or eight stages in the event loop in node. js, each with its own queue, which needs to wait until the queue processing in this phase is complete before entering another phase. The phases are converted to each other, and the cycle order is not completely fixed, because many of the stages are triggered by external events. Among the more important are three:
    1. Timer Stage Timers:
      The timer stage performs the timer task (SetTimeOut (), SetInterval ()).
    2. Polling Phase poll:
The polling phase is triggered by I/O events, such as ' Connect ', ' data ', and so on.          This is a relatively heavy/important phase because most of the program functions are for I/O data. This phase handles the tasks in the timer task and the poll queue, with specific logic:
      • Handle the timer task that expires, and then
      • Process queue tasks until the queue is empty or reaches the upper limit
      • If the queue task is gone:
        • If there is a setimmediate (), terminate the polling phase and enter the inspection phase to execute;
        • If there is no setimmediate (), then see if there is no expiration timer, some words go back to the timer stage to execute the callback function;
    1. Check the inspection stage:
When the polling phase is idle and already has setimmediate (), it goes through the inspection phase and executes. Two more minor but also listed in the table:
    1. I/O phase:
This stage handles I/O exception errors;
    1. ' Close ' event callback:
This stage handles various ' close ' event callbacks; about SetTimeout (), Setimmediate (), Process.nexttick ():
    • SetTimeout () executes the callback function as soon as possible after a certain time value;
    • Setimmediate () executes the callback function once the polling phase is complete ;
    • Process.nexttick () is processed immediately after the end of the current call stack , and must be "before the event loop continues";
Priority order from high to Low: Process.nexttick () > Setimmediate () > SetTimeout () Note: This is only the case in most cases, the polling phase (in the I/O callback). For example, when comparing setimmediate () and SetTimeout (), the stage/context is differentiated. another:For the call stack, the event loop can also refer to this article: https://blog.risingstack.com/node-js-at-scale-understanding-node-js-event-loop/ In this article, the event tasks are distinguished from large tasks (macro task), Small Tasks (micro Task), and each event loop handles only one large task, but all small tasks are processed. This is different from the previous article.

Examples of microtasks:

    • process.nextTick
    • promises
    • Object.observe

Examples of macrotasks:

    • setTimeout
    • setInterval
    • setImmediate
    • I/O

node. js Event Loop

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.