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
- 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