有没有比下面的pausecomp函数(取自此处)更好的方法来设计JavaScript中的睡眠?
function pausecomp(millis)
{
var date = new Date();
var curDate = null;
do { curDate = new Date(); }
while(curDate-date < millis);
}
这不是JavaScript中的Sleep的重复-动作之间的延迟;我希望在函数的中间有一个真正的睡眠,而不是在代码执行之前有一段延迟。
如果您真的想完全阻塞主线程并防止事件循环从事件队列中拉出,那么这里有一个很好的方法可以做到这一点,而不需要创建任何函数、新的Date对象或泄漏任何变量。我知道这个愚蠢的问题已经有一百万个答案了,但我没有看到有人使用这个精确的解决方案。这仅适用于现代浏览器。
警告:这不是你会投入生产的东西。它只是有助于理解浏览器事件循环。它可能对任何测试都没有用处。它不像一个正常的系统睡眠函数,因为JavaScript运行时仍然在每个循环中工作。
for (let e = performance.now() + 2000; performance.now() < e; ) {}
这里使用setTimeout回调,即使它几乎立即进入事件队列,也要在至少两秒后才能调用:
setTimeout(function() {
console.log("timeout finished");
}, 0);
for (let e = performance.now() + 2000; performance.now() < e; ) {}
console.log("haha wait for me first");
您将经历大约两秒的暂停,然后看到:
haha wait for me first
timeout finished
在Date.now()上使用performance.now(()的好处是Date对象是
受到时钟偏斜和系统时钟调整的影响。这个时间的价值可能不总是单调增加随后的值可以减小或保持不变。*
通常,performance.now()更适合高精度地测量时间差异。
使用for循环的好处是可以在运行之前设置块的本地变量。这允许您在循环外进行加法运算,同时仍然是“单行”。这应该可以最大限度地减少这种热循环燃烧的CPU负载。
一个用于休眠的函数,使用同步调用让操作系统执行。使用您喜欢的任何操作系统休眠命令。在使用CPU时间的意义上,它并不忙着等待。
我在一个不存在的地址上选择了ping。
const cp = require('child_process');
function sleep(ms)
{
try{cp.execSync('ping 192.0.2.0 -n 1 -w '+ms);}
catch(err){}
}
测试以验证其是否有效
console.log(Date.now());
console.log(Date.now());
sleep(10000);
console.log(Date.now());
console.log(Date.now());
以及一些测试结果。
1491575275136
1491575275157
(10秒后)
1491575285075
1491575285076