您的位置:

Node.js setTimeout详解

一、setTimeout简介

setTimeout是Node.js提供的一个全局函数,用于在指定时间后执行一个回调函数。

setTimeout(callback, delay, [arg], [...])

其中,callback是被调用的函数,delay是延迟时间(单位为毫秒),arg是被传递给callback的参数(可选)。

二、使用setTimeout执行延时操作

setTimeout最常用的场景是执行延时操作。

console.log('start');
setTimeout(function() {
    console.log('delayed operation');
}, 3000);
console.log('end');

上面代码的输出结果为:

start
end
delayed operation

可以看到,delayed operation是在start和end之后3秒钟才被输出的。这就说明了setTimeout的延时特性。

三、使用setTimeout执行周期性操作

setTimeout除了可以执行延时操作,还可以执行周期性操作。

console.log('start');
setTimeout(function repeat() {
    console.log('repeated operation');
    setTimeout(repeat, 1000);
}, 1000);
console.log('end');

上面代码的输出结果为:

start
end
repeated operation
repeated operation
repeated operation
...

可以看到,repeated operation是每间隔1秒钟就被输出一次的。这是因为在每次执行完callback之后,我们在callback内部又设置了下一次的setTimeout。

四、setTimeout的返回值和取消操作

setTimeout的返回值是一个唯一的定时器标识符(timer identifier),可以用来取消操作。

var timerId = setTimeout(function() {
    console.log('delayed operation');
}, 3000);

console.log(timerId); // 输出一个非零整数

clearTimeout(timerId);
console.log(timerId); // 输出undefined

上面的代码根据timerId来取消了setTimeout操作。clearTimeout函数的参数即为setTimeout返回的timer identifier。

五、setTimeout的内存泄漏问题

使用setTimeout时需要注意内存泄漏问题。如果一个回调函数包含了对它外部的资源的引用,那么这个回调函数不会被及时清理,从而导致引用的资源也无法及时清理,造成内存泄漏。

function log() {
    console.log('Operation done!');
}

console.log('start');
setTimeout(log, 3000);
console.log('end');

上面代码中的log函数引用了console对象,而console对象是个全局对象。因此,在回调函数执行前,它是不会被清理的,而我们在回调函数里面没有再次引用console对象,使得console对象也无法得到及时的清理,从而造成了内存泄漏。

解决这个问题的方法是通过闭包使得回调函数内部不引用外部的资源。

function log() {
    return function() {
        console.log('Operation done!');
    }
}

console.log('start');
setTimeout(log(), 3000);
console.log('end');

通过返回一个函数,在回调函数内部执行操作,这样就避免了回调函数引用了外部资源的问题。