当前位置: 首页 > 后端技术 > Node.js

节点端事件循环机制(Part2-Timers,Immediates,NextTicks)

时间:2023-04-04 01:18:28 Node.js

欢迎回来。在第一篇文章中,描述了NodeJS事件循环的整体情况。在本节中,将详细讨论三个代码示例。重要队列。它们是process.nextTick的定时器、立即数和回调。文章指南EventLoopTimers,Immediates,NextTicks(本文)Promises,Next-Ticks,ImmediatesHandlingI/OThebesteventlooppracticetimers,microtasksinNodev11ChangesHappenedI/OStarvationExample1这引入了一个新问题。使用process递归/重复地将事件添加到nextTick队列。nextTick函数会导致I/O和其他队列永远饿死。我们可以使用下面的简单脚本来模拟这种情况。constfs=require('fs');函数addNextTickRecurs(count){让self=this;if(self.id===undefined){self.id=0;}if(self.id===count)返回;process.nextTick(()=>{console.log(`process.nextTickcall${++self.id}`);addNextTickRecurs.call(self,count);});}addNextTickRecurs(Infinity);setTimeout(控制台.log.bind(console,'omg!setTimeoutwascalled'),10);setImmediate(console.log.bind(console,'omg!setImmediate也被调用'));fs.readFile(__filename,()=>{console.log('我的天啊!调用了文件读取完成回调!');});console.log('开始');你可以看到输出是nextTick回调调用的无限循环,以及setTimeout、setImmediate和fs。读取文件。从未调用readFile回调。startedprocess.nextTick调用1process.nextTick调用2process.nextTick调用3process.nextTick调用4process.nextTick调用5process.nextTick调用6process.nextTick调用7process.nextTick调用8process.nextTick调用nextTick调用9process.nextTick调用11process.nextTick调用12....示例2constfs=require('fs');fs.readFile(__filename,()=>{setTimeout(()=>{console.log('timeout')},0);setImmediate(()=>{console.log('immediate')})});接下来我们来看看它的执行流程。一开始,这个程序使用fs.readFile异步读取当前文件。它提供了一个在读取文件后触发的回调函数。然后事件循环开始。读取文件后,它将在事件循环的I/O队列中添加事件(要执行的回调)。节点正在等待任何I/O事件,因为没有其他事件要处理。然后它将在I/O队列上看到文件读取事件并执行它。在回调的执行过程中,timer被添加到timerheap,Immediates被添加到Immediatesqueue现在我们知道eventloop处于I/O阶段。由于没有任何I/O事件要处理,事件循环转到即时阶段并立即执行即时回调。在事件循环的下一个循环中,它将看到过期的计时器并执行计时器回调。例三setImmediate(()=>console.log('thisissetimmediate1'));setImmediate(()=>console.log('thisissetimmediate2'));setImmediate(()=>console.log('这是设置立即3'));setTimeout(()=>console.log('这是设置超时1'),0);setTimeout(()=>{console.log('这是设置超时2');process.nextTick(()=>console.log('这是在setTimeout中添加的process.nextTick'));},0);setTimeout(()=>console.log('这是设置超时3'),0);setTimeout(()=>console.log('这是设置超时4'),0);setTimeout(()=>console.log('这是设置超时5'),0);process.nextTick(()=>console.log('这是process.nextTick1'));process.nextTick(()=>{process.nextTick(console.log.bind(console,'这是内nexttickinsidenexttick'));});process.nextTick(()=>console.log('thisisprocess.nextTick2'));process.nextTick(()=>console.log('thisisprocess.nextTick3'));process.nextTick(()=>console.log('这是process.nextTick4'));首先,一些事件会添加到事件队列如下3immediates5timerbackoff5nexttickbackoff当事件循环开始时,会通知nexttick队列,并开始处理nexttickcallbacks在执行第二个nexttick时回调,一个新的下一个报价回调被添加到下一个报价队列的末尾,并将在下一个报价队列的末尾执行。将执行过期计时器的回调。在第二个定时器回调函数的执行过程中,一个事件被添加到下一个滴答队列中。一旦所有过期的计时器回调都已执行,事件循环将看到下一个计时器队列中有一个事件(在执行第二个计时器回调期间添加)。然后事件循环将执行它。由于没有要处理的I/O事件,事件循环将移动到立即队列并处理立即队列。执行结果如下:thisisprocess.nextTick1thisisprocess.nextTick2thisisprocess.nextTick3thisisprocess.nextTick4thisisinnernexttickinsidenexttickthissettimeout1thissettimeout2thissettimeout3thissettimeout4这个是settimeout5这个是process.nextTick在setTimeout里面加的这个是setimmediate1这个是setimmediate2这个是setimmediate3参考https://jsblog.insiderattack....(自带梯子)