有没有比下面的pausecomp函数(取自此处)更好的方法来设计JavaScript中的睡眠?

function pausecomp(millis)
{
    var date = new Date();
    var curDate = null;
    do { curDate = new Date(); }
    while(curDate-date < millis);
}

这不是JavaScript中的Sleep的重复-动作之间的延迟;我希望在函数的中间有一个真正的睡眠,而不是在代码执行之前有一段延迟。


当前回答

2017-2021更新

自2009年提出这个问题以来,JavaScript已经有了很大的发展。所有其他答案现在都过时或过于复杂。以下是当前的最佳实践:

function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

或作为一个内衬:

await new Promise(r => setTimeout(r, 2000));

作为一项功能:

const sleep = ms => new Promise(r => setTimeout(r, ms));

或使用字体:

const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms));

将其用作:

await sleep(<duration>);

演示:

功能睡眠(ms){return new Promise(resol=>setTimeout(resolve,ms));}异步函数demo(){for(设i=0;i<5;i++){console.log(`等待${i}秒…`);等待睡眠(i*1000);}console.log('Done');}demo();

注意,

await只能在前缀为async关键字的函数中执行,或者在越来越多的环境中在脚本的顶层执行。await只暂停当前的异步函数。这意味着它不会阻止脚本的其余部分的执行,这在大多数情况下都是您想要的。如果您确实需要一个阻塞构造,请使用Atomics.wait查看这个答案,但请注意,大多数浏览器都不允许在浏览器的主线程上使用它。

两个新的JavaScript功能(截至2017年)帮助编写了这个“睡眠”函数:

Promises是ES2015(又称ES6)的原生功能。我们还在睡眠函数的定义中使用箭头函数。async/await特性允许代码显式地等待承诺(解决或拒绝)。

兼容性

承诺在Node v0.12+中得到支持,在浏览器中得到广泛支持,IE除外async/await登陆V8,自Chrome 55(2016年12月发布)以来默认启用它于2016年10月登陆Node 7并于2016年11月登陆Firefox Nightly

如果出于某种原因,您使用的Node早于7(已于2017年到期),或者针对的是旧浏览器,则仍可通过Babel(一种将JavaScript+新功能转换为普通旧JavaScript的工具)使用async/await,并使用将async-to-generator转换为生成器插件。

其他回答

一行使用Promise

const wait = t => new Promise(s => setTimeout(s, t, t));

带有中止信号的字体

const wait = (x: number, signal?: AbortSignal): Promise<number> => {
  return new Promise((s, f) => {
    const id = setTimeout(s, x, x);
    signal?.addEventListener('abort', () => {
      clearTimeout(id);
      f('AbortError');
    });
  });
};

Demo

const wait=t=>new Promise(s=>setTimeout(s,t));//用途异步函数demo(){//倒计时设i=6;而(i-){等待等待(1000);控制台日志(i);}//数字0到5的总和,延迟1秒constsum=await[…Array(6).keys()].reduce(async(a,b)=>{a=等待a;等待等待(1000);常量结果=a+b;console.log(`${a}+${b}=${result}`);返回结果;},承诺.决议(0));console.log(“sum”,总和);}demo();

如果你喜欢建议,不要失去表现。setTimeout是您的预期睡眠。然而,如果您需要一种语法,其中代码被睡眠“中间分割”,我们可以这样做:

sleep = function(tm, fn){
   window.setTimeout(fn, tm);
}

然后,准备如下功能:

var fnBeforeSleep = function(){

  // All code before sleep

}

var fnAfterSleep = function(){

  // All code after sleep

}

然后:

fnBeforeSleep();
sleep(2000, fnAfterSleep);

// Yep! Syntactically, it is very close to:

fnBeforeSleep();
sleep(2000);
fnAfterSleep();

或者只创建一个:

function yourFunction(){

   // Do something
   setInterval(myFunc(), 1000);
   // Do something else
}

function myFunc(){
   return;
}

这将只等待指定的时间间隔并调用函数,而该函数将不执行任何操作。

有一个新的库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);

并且内置支持在每次迭代之间“休眠”的循环。

如果你写一个这样的睡眠函数

var sleep = function(period, decision, callback){
    var interval = setInterval(function(){
        if (decision()) {
            interval = clearInterval(interval);
            callback();
        }
    }, period);
}

你有一个异步函数可以多次调用,

var xhr = function(url, callback){
    // Make an Ajax request
    // Call a callback when the request fulfils
}

您的项目设置如下:

var ready = false;

function xhr1(){
    xhr(url1, function(){ ready = true;});
}
function xhr2(){
    xhr(url2, function(){ ready = true; });
}
function xhr3(){
    xhr(url3, function(){ ready = true; });
}

然后您可以执行以下操作:

xhr1();
sleep(100, function(){ return done; }, xhr2);
sleep(100, function(){ return done; }, xhr3);
sleep(100, function(){ return done; }, function(){
    // Do more
});

而不是像这样无休止的回调缩进:

xhr(url1, function(){
    xhr2(url2, function(){
        xhr3(url3, function(){
            // Do more
        });
    });
});