1. Why does NodeJS have an event loop event processing mechanism

Nodejs is event-driven and non-blocking but threaded, making applications lighter and more efficient. When the application needs related I/O operations, the thread does not block, but hands off the I/O operations to the underlying class library (such as Libuv). At this point, the NodeJS thread will take care of other tasks, and when the underlying library has finished processing the related I/O operations, it will return the initiative to the NodeJS thread. Therefore, the function of the Event loop is to schedule the thread, such as the nodeJS single thread to handle the subsequent work after the underlying library processes the I/O operation. That is, when the Nodejs program starts, it opens an event loop for asynchronous API scheduling, schedule timers, and the callback process.nexttick ().

Nodejs is single-threaded, but it is still multithreaded when the underlying library handles asynchronous operations.

2. Ask questions

What happens when we run the following code in the Node environment?

let fs = require('fs');
setTimeout(function(){
    Promise.resolve().then(()=>{
        console.log('then2');
    })
},0);
Promise.resolve().then(()=>{
    console.log('then1');
});
fs.readFile('./gitigore'.function(){
    process.nextTick(function(){
        console.log('nextTick')})setImmediate(()=>{
        console.log('setImmediate')}); });Copy the code

The result in the Node environment is

then1
then2
nextTick
setImmediate
Copy the code

3. Before starting the event loop, nodeJS is initialized

This result comes from the sequence of events that Node.js loops through. The Node.js event loop, Timers, and process.nexttick ()

┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ ┌ ─ > │ timers (timer) perform │ │ |setThe Timeout andsetThe Interval callback │ │ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┬ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ │ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ │ │ I/O callbacks │ │ processing network, the flow, TCP error │ │ │ callback │ │ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┬ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ │ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ │ │ idle, Prepare │ │ │ node internal use │ │ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┬ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ │ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ │ incoming: │ ├ ──┤ connections, │ ├ ─ data, │ ├ ─ data, │ ├ ─ data, │ ├ ─ data, │ ├ ─ data, │ ├ ─ data, │ ├ ─ data, │ ├ ─ data, │ ├ ─ data, │ ├ ─ data, │ ├ ─ data, │ ├ ─ data, │ ├ ─ data. Whether etc. │ │ │ timer when │ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ │ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┬ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ │ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ │ │ check │ │ │ to depositsetImmediate correction │ │ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┬ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ │ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┴ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ └ ─ ─ ┤ close callbacks │ │ closed callbacks such as │ │ socket. On ('close') │ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘Copy the code

Where, each box is a stage of the Event Loop. When the Event Loop enters a certain stage, the callback in the queue of the stage will be executed until the queue is empty.

Several queue

Timers Queue - I/O Queue - Input and output Queue Check Queue - Check Queue Close queue-guangbi QueueCopy the code

In addition to the task type of the loop phase above, there are micro tasks shared by the browser and NodeJS, and Node’s process.nexttick. The corresponding queues are called MircoTask Queue and NextTick Queue respectively

4. After the cycle starts:

According to the above six stages, take out all tasks in the current stage for execution, empty the NextTick queue and the micro-task queue, and then execute the next stage. After the completion of all six stages, enter the next cycle.

In other words, it is expressed by a graph

  1. Combining with the code
let fs = require('fs');
setTimeout(function(){
   Promise.resolve().then(()=>{
       console.log('then2');
   })
},0);
Promise.resolve().then(()=>{
   console.log('then1');
});
fs.readFile('./gitigore'.function(){
   process.nextTick(function(){
       console.log('nextTick')})setImmediate(()=>{
       console.log('setImmediate')}); });Copy the code

Looking back at the code we showed at the beginning, here we clearly have it in our queue

setTimeout
Promise.resolve().then
fs.readFile
Copy the code

The three main task queues are based on the cycle phases, and we present and execute the code in the order of the cycle phases

/ / empty TimerQueuesetThe Timeout (...). // Clear the microtasks in this process //thenPromise.resolve().then()=>{console.log()'then1'); // then1}); Promise.resolve().then(()=>{ console.log('then2'); // thenFs.readfile (...) NextTick Queue process.nexttick (function(){
   console.log('nextTick') // nextTick}) // Clear the micro queuesetImmediate(()=>{
   console.log('setImmediate') / /setImmediate
});

Copy the code