Node.js 中的定时器

    Node.js 中的 API 函数提供了几种方式,允许代码从现在时间之后的某个时刻开始执行。以下给出的函数看上去很相似,因为它们在大多数浏览器中都可用。但是 Node.js 实际上提供了它自己的实现。定时器与系统非常紧密地结合在一起,尽管这些 API 是浏览器中函数的翻版,但是仍然在实现上有所不同。

    setTimeout() 可被用来在一段指定时间之后执行某个代码任务。此函数与浏览器 JavaScript 函数 window.setTimeout() 很相似,但是你不能把一串字符串传入执行。

    setTimeout() 接受一个可执行的函数作为其第一个参数,然后有一个毫秒为单位的延时时间作为第二个参数。其余的参数也可纳入其中,作为传给此函数的参数使用。以下是一个例子:

    因为使用了 setTimeout(),以上函数 myFunc() 将在 1500 毫秒(或者1.5秒)左右时执行。

    设置的定时间隔不能保证每次都是以 精准 的毫秒间隔数执行代码,这是因为其它阻塞或者正在事件轮询上处理的代码将推迟此定时的执行。唯一 保证的是定时器不会比声明的时间间隔 提早 执行。

    setImmediate() 将在当前事件轮询的末尾处执行。 本代码将在当前事件轮询中的任何 I/O 操作 ,在任何下一轮定时器 执行。代码执行可以被认为是“在此之后立即执行”,这意味着任何紧跟着 setImmediate() 函数调用将在 setImmediate() 函数参数前执行。

    setImmediate() 的第一个参数是要执行的函数,当执行时,后面的参数将作为参数传入这个函数中。这是一个例子:

    1. console.log('before immediate');
    2. setImmediate((arg) => {
    3. }, 'so immediate');
    4. console.log('after immediate');

    传入 setImmediate() 的上述函数将在任何可执行的代码执行完后执行,所以输出结果是:

    setImmediate() 返回一个 Immediate 对象,它可以被用于取消安排的定时任务(见下面的 clearImmediate() )。

    注意:不要把 setImmediate()process.nextTick() 相混淆。它们有一些主要的差别:第一, process.nextTick() 将在任何设置好的 以及任何安排好的 I/O 执行。第二, process.nextTick() 是不可擦除的,换句话说,一旦有代码使用 process.nextTick() 执行,执行无法中断,这就像一个普通函数一样,具体可以参考来更好地理解 process.nextTick() 的操作。

    1. function intervalFunc() {
    2. console.log('Cant stop me now!');
    3. }
    4. setInterval(intervalFunc, 1500);

    在上面的例子中,intervalFunc() 每 1500 毫秒执行一次(或每 1.5 秒执行一次),直到它被终止(见下)。

    就像 setTimeout()setInterval() 同样返回一个 Timeout 对象,它可以被引用并且改变设定的定时器。

    如果 TimeoutImmediate 需要被取消,我们该怎么办?setTimeout()setImmediate()setInterval() 返回一个定时器对象,它可以被用来引用设置过的 TimeoutImmediate 对象。通过把该对象传入 clear 函数中,那个对象就会被终止执行。这些可接受的函数是 clearTimeout()clearImmediate()clearInterval()。看下面例子:

    你已经记住了 对象是通过 setTimeoutsetInterval 返回的。 Timeout 对象提供了两个针对 Timeout 行为的函数: unref()ref()。如果有一个 Timeout 对象是通过 set 函数设定排程的,unref() 就可以用于那个对象。这会对它产生一些轻微的改变,那就是 如果它是最后的执行代码 ,将不会调用 Timeout 对象。

    相似的是,Timeout 对象有 unref() 方法可以被调用从而移除通过在相同的 Timeout 对象上调用了 ref() 之后所施加的行为,从而保证它的执行。小心一点,它并不会 准确地 恢复到初始化的行为状态。请见下面的例子:

    1. const timerObj = setTimeout(() => {
    2. console.log('will i run?');
    3. // if left alone, this statement will keep the above
    4. // timeout from running, since the timeout will be the only
    5. // thing keeping the program from exiting
    6. timerObj.unref();
    7. // we can bring it back to life by calling ref() inside
    8. // an immediate
    9. setImmediate(() => {
    10. timerObj.ref();