有没有比下面的pausecomp函数(取自此处)更好的方法来设计JavaScript中的睡眠?
function pausecomp(millis)
{
var date = new Date();
var curDate = null;
do { curDate = new Date(); }
while(curDate-date < millis);
}
这不是JavaScript中的Sleep的重复-动作之间的延迟;我希望在函数的中间有一个真正的睡眠,而不是在代码执行之前有一段延迟。
这里大多数解决方案的问题是它们倒带堆栈。在某些情况下,这可能是一个大问题。在这个例子中,我展示了如何以不同的方式使用迭代器来模拟真实的睡眠。
在本例中,生成器正在调用自己的next(),因此一旦它启动,它就自己运行了。
var h = a();
h.next().value.r = h; // That's how you run it. It is the best I came up with
// Sleep without breaking the stack!!!
function *a(){
var obj = {};
console.log("going to sleep....2s")
setTimeout(function(){obj.r.next();}, 2000)
yield obj;
console.log("woke up");
console.log("going to sleep no 2....2s")
setTimeout(function(){obj.r.next();}, 2000)
yield obj;
console.log("woke up");
console.log("going to sleep no 3....2s")
setTimeout(function(){obj.r.next();}, 2000)
yield obj;
console.log("done");
}
2019更新使用Atomics.wait
它应该在Node.js 9.3或更高版本中工作。
我在Node.js中需要一个非常精确的计时器,它非常适合。
然而,浏览器中的支持似乎非常有限。
设ms=10000;Atomics.wait(新Int32Array(新SharedArray Buffer(4)),0,0,ms);
运行了几次10秒计时器基准测试。
使用setTimeout,我得到的错误高达7000微秒(7毫秒)。
使用Atomics,我的错误似乎保持在600微秒(0.6毫秒)以下
2020年更新:总结
function sleep(millis){ // Need help of a server-side page
let netMillis = Math.max(millis-5, 0); // Assuming 5 ms overhead
let xhr = new XMLHttpRequest();
xhr.open('GET', '/sleep.jsp?millis=' + netMillis + '&rand=' + Math.random(), false);
try{
xhr.send();
}catch(e){
}
}
function sleepAsync(millis){ // Use only in async function
let netMillis = Math.max(millis-1, 0); // Assuming 1 ms overhead
return new Promise((resolve) => {
setTimeout(resolve, netMillis);
});
}
function sleepSync(millis){ // Use only in worker thread, currently Chrome-only
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, millis);
}
function sleepTest(){
console.time('sleep');
sleep(1000);
console.timeEnd('sleep');
}
async function sleepAsyncTest(){
console.time('sleepAsync');
await sleepAsync(1000);
console.timeEnd('sleepAsync');
}
function sleepSyncTest(){
let source = `${sleepSync.toString()}
console.time('sleepSync');
sleepSync(1000);
console.timeEnd('sleepSync');`;
let src = 'data:text/javascript,' + encodeURIComponent(source);
console.log(src);
var worker = new Worker(src);
}
其中服务器端页面,例如sleep.jsp,看起来像:
<%
try{
Thread.sleep(Long.parseLong(request.getParameter("millis")));
}catch(InterruptedException e){}
%>
有一个新的库Sequencr.js,它将函数与超时巧妙地链接在一起,这样就可以避免回调。
结果是:
setTimeout(function(timeout){
function1();
setTimeout(function(timeout){
function2();
setTimeout(function(timeout){
function3();
}, timeout, timeout)
}, timeout, timeout)
}, 10, 10);
在这方面:
Sequencr.chain([function1, function2, function3], 10);
并且内置支持在每次迭代之间“休眠”的循环。