本章介绍Node.js的timer模块,该模块API可以提供定时器的功能。
Node. js的timer模块公开了一个全局API,用于调度在将来某个时间段调用的函数。因为timer函数是全局变量,所以不需要调用类似require('timers')的方式来使用API。
Node. js中的timer函数实现了与Web浏览器提供的定时器API类似的API,但是使用了不同的内部实现(基于Node.js事件循环构建)。
timer模块常用的类有Immediate类和Timeout类。
Immediate对象在内部创建,并从setImmediate()返回。它可以传给clearImmediate()以取消计划的操作。
默认情况下,当预定immediate时,只要immediate激活,Node.js事件循环将继续运行。setImmediate()返回的Immediate对象导出immediate.ref()和immediate.unref()函数,这些函数可用于控制此默认行为。
Immediate. hasRef()方法如果返回为true,则Immediate对象将使Node.js事件循环保持活动状态。
immediate. ref()方法调用时,只要Immediate处于活动状态,就会请求Node.js事件循环不会退出。多次调用immediate.ref()将无效。
默认情况下,所有Immediate对象都是ref的,通常不需要调用immediate.ref(),除非之前调用了immediate.unref()。
immediate. unref()方法调用时,活动的Immediate对象不需要Node.js事件循环保持活动状态。如果没有其他活动保持事件循环运行,则进程可以在调用Immediate对象的回调之前退出。多次调用immediate.unref()将无效。
Timeout对象在内部创建,并从setTimeout()和setInterval()返回。它可以传给clearTimeout()或clearInterval()以取消计划的操作。
默认情况下,当使用setTimeout()或setInterval()预定定时器时,只要定时器处于活动状态,Node.js事件循环将继续运行。这些函数返回的每个Timeout对象都会导出timeout.ref()和timeout.unref()函数,这些函数可用于控制此默认行为。
timeout. hasRef()方法如果返回为true,则Timeout对象将使Node.js事件循环保持活动状态。
timeout. ref()方法调用时,只要Timeout处于活动状态,就会请求Node.js事件循环不会退出。多次调用timeout.ref()将无效。
默认情况下,所有Timeout对象都是ref的,通常不需要调用timeout.ref(),除非之前调用了timeout.unref()。
将定时器的开始时间设置为当前时间,并重新安排定时器以在之前指定的持续时间内调用其回调,并将其调整为当前时间。这对于在不分配新JavaScript对象的情况下刷新定时器非常有用。
在已调用其回调的定时器上使用此选项将重新激活定时器。
timeout. unref()方法调用时,活动的Timeout对象不需要Node.js事件循环保持活动状态。如果没有其他活动保持事件循环运行,则进程可以在调用Timeout对象的回调之前退出。多次调用timeout.unref()将无效。
调用timeout.unref()会创建一个内部定时器,它将唤醒Node.js事件循环。创建太多这些定时器可能会对Node.js应用程序的性能产生负面影响。
Node. js中的定时器是一种会在一段时间后调用给定的函数的内部构造。何时调用定时器函数取决于用来创建定时器的方法,以及Node.js事件循环正在执行的其他工作。
Node. js定义了setImmediate(callback[,……args])方法,用于设定定时器为立即执行定时器。其中参数:callback<Function>指在当前回合的Node.js事件循环结束时调用的函数;……args<any>指当调用callback时传入的可选参数。
当多次调用setImmediate()时,callback函数将按照创建它们的顺序排队等待执行。每次事件循环迭代都会处理整个回调队列。如果立即(immediate)定时器是从正在执行的回调排入队列,则直到下一次事件循环迭代才会触发。
如果callback不是函数,则抛出TypeError。
此方法具有使用util.promisify()的用于Promise的自定义变体。
setInterval(callback, delay[,……args])方法,用于设定定时器执行的周期,定时器每隔delay毫秒重复执行一次。其中参数:callback<Function>指在当前回合的Node.js事件循环结束时调用的函数;delay<number>指调用callback之前等待的毫秒数;……args<any>指当调用callback时传入的可选参数。
当delay大于2 147 483 647(即32位整型的最大值)或小于1时,delay将设置为1。
如果callback不是函数,则抛出TypeError。
setTimeout(callback, delay[,……args])方法,用于在上一次定时器执行的delay毫秒之后设定定时器执行时机。其中参数:callback<Function>指在当前回合的Node.js事件循环结束时调用的函数;delay<number>指调用callback之前等待的毫秒数;……args<any>指当调用callback时传入的可选参数。
可能不会精确地在delay毫秒时调用callback。Node.js不保证回调被触发的确切时间,也不保证它们的顺序。callback会在尽可能接近指定的时间调用。
同setInterval一样,当delay大于2 147 483 647(即32位整型的最大值)或小于1时,delay将设置为1。
如果callback不是函数,则抛出TypeError。
此方法具有使用util.promisify()的用于Promise的自定义变体。
setInterval和setTimeout这两个方法的参数是一样的,其区别在于定时执行的时点不同。
setInterval是每间隔一定时间执行一次,循环往复。例如,每隔1秒执行一次,60秒过后执行了60次。setTimeout是过了一定时间执行一次,只执行一次。例如,隔1秒后执行一次,过了十万八千秒后也只在第一秒执行了一次。
图6-1展示了setInterval和setTimeout的执行差异。
图6-1 setInterval和setTimeout的异同
在图6-1中,setInterval每个定时器执行的间隔都是固定的,不管doStuff需要执行多久,都能按照固定的时间间隔来执行。而在setTimeout中,下一个定时的时间间隔取决于doStuff的执行耗时,换言之,下个定时的时间间隔可以等同于doStuff的执行耗时加上delay。