如果你熟悉客户端Javascript编程,你可能已经使用setTimeout和setInterval函数。这两个函数允许在一段时间内运行一个函数的延迟。

复制代码代码如下所示:

无功一秒= 1000 * 1 = 1000; / /秒×1毫秒

setTimeout(){()函数(

document.write(你好那里。);

},一秒);



setInterval允许重复执行功能在指定的时间间隔。如果下面的代码注入到网页,你好有增加到每秒页面文件。

复制代码代码如下所示:

无功一秒= 1000 * 1 = 1000; / /秒×1毫秒

setInterval(){()函数(

document.write(你好那里。);

},一秒);



因为Web已经成为构建应用程序的一个平台,而不是简单的静态页面,这样一个类似的需求出现。这些任务规划功能,帮助开发者实现形式定期验证,延迟的远程数据同步,或者UI的交互需要一个延迟反应。这些方法也由节点完全实现。在服务器端,你可以用它们来重复或延迟的许多任务,如缓存失效,连接池清洗、会话过期的投票,等等。

使用setTimeout延迟执行函数

setTimeout可以执行计划,在将来的某个时间运行指定的功能,如:

复制代码代码如下所示:

无功timeout_ms = 2000; / / 2秒

VaR超时= setTimeout()函数(){

console.log(超时!;

},timeout_ms);



就像客户端Javascript的setTimeout接受两个参数。第一个参数是需要延迟的函数。第二个参数是延迟时间(毫秒)。

setTimeout返回一个超时处理。它是一个内部对象。它可以被称为清除定时器作为参数来取消计时器。另外,手柄没有效果。

使用清除定时器取消执行计划

一旦获得了超时处理,你可以使用清除定时器取消该功能的执行计划,这样:

复制代码代码如下所示:

无功timeouttime = 1000; / /一秒

VaR超时= setTimeout()函数(){

console.log(超时!;

}, timeoutTime);

ClearTimeout(超时);



在这个例子中,定时器永远不会被触发,也不会输出超时!你也可以在将来的任何时候取消执行计划,如下面的例子:

复制代码代码如下所示:

VaR超时= setTimeout(){(函数(){



console.log(超时!;



},2000);



setTimeout(函数B(){)



ClearTimeout(超时);



},1000);



该代码指定了21个函数和B函数。函数a在2秒内执行。B计划在1秒之后执行,因为函数B首先执行,它取消了A的执行计划,所以A永远不会运行。

函数的重复执行计划

setInterval类似setTimeout,但它重复的函数在指定的时间间隔。你可以用它定期触发程序完成一些任务就像清理、收集、记录、获取数据、投票,和其他需要重复的任务。

下面的代码每隔一秒钟输出一次到控制台的滴答声。

复制代码代码如下所示:

var周期= 1000; / 1秒

setInterval(){()函数(

console.log(√);

},周期);



如果你不想让它跑下去,你可以使用clearInterval()来取消计时器。

setInterval返回一个执行计划的处理,可以作为一个参数clearInterval取消执行计划:

复制代码代码如下所示:

VaR区间= setInterval(function()){

console.log(√);

},1000);

…

ClearInterval(间隔);



使用process.nexttick延迟函数执行事件循环的下一轮

有时,客户端的Javascript程序员使用setTimeout(回调,0)在很短的时间内任务延迟,第二个参数是0毫秒。它讲述了Javascript运行时,当所有的待处理事件,回调函数是立即执行。有时这种技术用于延迟执行的操作,不需要立即执行。例如,有时你需要开始播放动画或做一些其他的计算在用户事件处理。

在节点中,它类似于事件循环的字面含义。事件循环在处理事件队列的循环中运行。每一轮的事件周期称为刻度。

你可以调用回调函数,一旦事件周期开始下一轮(下打勾)执行,这也是process.nexttick原则,而setTimeout和setTimeout使用Javascript运行时执行队列而不是事件循环。

利用process.nexttick(回调)而不是setTimeout(回调,0),你的回调函数将事件队列中处理后立即执行,这比Javascript超时队列更快(CPU时间)。

您可以将函数推迟到下一轮事件,然后再运行如下:

复制代码代码如下所示:

process.nexttick(函数(){()

my_expensive_computation_function();

});



注意:流程对象是少数几个节点的全局对象之一。

阻塞事件循环

节点和Javascript的运行时间是单线程事件循环,每个周期。运行时调用相应的回调函数队列中处理下一个事件,当事件完成,事件循环获取执行结果和过程的下一个事件,如此反复直到事件队列是空的。如果一个回调函数需要长时间运行,它将不活动周期期间处理其他悬浮事件,这将减缓应用程序或服务。

在处理事件时,如果使用内存敏感或处理器敏感的功能,事件循环将变慢,导致大量事件积累,无法及时处理,甚至阻塞队列。

请看下面的阻塞事件循环的示例:

复制代码代码如下所示:

process.nexttick(功能nexttick1(){)

var a=0;

当(真){

++;

}

});

process.nexttick(功能nexttick2(){)

console.log(下勾);

});

setTimeout(功能超时(){)

console.log(超时);

},1000);



在这种情况下,nexttick2和超时功能没有机会来看,无论他们怎样等待,因为事件循环的nexttick功能无限循环受阻。即使超时函数预定在1秒之后执行,它也不会运行。

使用setTimeout时,回调函数添加到执行队列,在这种情况下,他们甚至没有添加到队列中。这是一个极端的例子,但你可以看到,运行一个处理器敏感的任务可能堵塞或减缓事件循环。

退出事件周期

与process.nexttick,非关键任务可以推迟到蜱执行下一轮,这将释放事件循环,使其能够继续执行其他悬浮事件。

请看下面的例子。如果您想删除一个临时文件,但不希望数据事件的回调函数等待IO操作,您可以像这样延迟它。

复制代码代码如下所示:

Stream.on(数据

Stream.end(我);

process.nexttick(函数(){()

Fs.unlink( / / /文件路径);

});

});



使用setTimeout而setInterval保证功能执行序列化

假设你计划设计一个函数调用my_async_function,可以做一些功能,我 / O操作,如分析日志文件,并打算让它定期执行。你可以使用setInterval来实现它。

复制代码代码如下所示:

var间隔= 1000;

setInterval(){()函数(

my_async_function(函数(){()

console.log('my_async_function完成!;

});

}时间间隔是前面的,我补充说,作者应该是一个缺失的人。



你必须能够保证这些功能将不会在同一时间执行,但是如果你使用setInterval不能保证,如果my_async_function函数运行到一毫秒的间隔变长,他们将在同一时间执行,而不是根据串行执行的顺序。

译者注:(以下部分是添加到译者,而不是原来的内容)

为了便于理解内容的这一部分,您可以修改作者的代码,以便它能够实际运行:

复制代码代码如下所示:

var间隔= 1000;

setInterval(){()函数(

(功能my_async_function(){

setTimeout(){()函数(

console.log(1 );

},5000);

});

},区间);



当你运行这个代码,你会发现,等待5秒后,你好是输出每二。我们预计,当my_async_function执行完毕(5秒后),等待一次执行下一my_async_function,各输出应间隔6秒。这样的结果是由于my_async_function不执行串行,但多个同时运行。

因此,你需要一个my_async_function执行到下一个my_async_function执行力之间的间隔,只是时间间隔由变量指定的。你可以这样做:

复制代码代码如下所示:

var间隔= 1000; / 1

(函数(调度))第三

setTimeout(function(){ do_it)

my_async_function(函数(){ / /第五

console.log('async做!;

附表();

});

},区间);

}());第十行



在前面的代码中,一个名为第三行的函数被声明,并且在声明后立即调用它(第十行)。附表一第二功能将在运行do_it功能(指定区间)。1秒后,my_async_function功能的第五线将被调用时,它执行完毕后,打电话给自己的匿名回调函数(第六行),和匿名的回调函数将再次复位do_it执行计划,使它1秒后重新执行,这段代码将启动串行连续环。

总结

setTimeout()函数可以用来设定功能的执行计划和取消它的清除定时器()函数,也可以使用setInterval()函数的周期性的重复,因此,你可以使用clearInterval()取消重复执行计划。

如果事件循环利用处理器敏感操作受阻,这些功能原本计划要执行将推迟甚至不执行。所以不要在事件循环使用CPU敏感的操作。另外,你可以使用process.nexttick()函数的执行延迟到下一个事件循环圆。

当我 / O和setInterval()一起使用,你不能保证只有一个挂起的电话在任何时间点。然而,你可以通过使用递归函数和setTimeout()函数避免这个困难的问题。