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

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

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


当前回答

JavaScript是一个单线程执行环境。每个函数都只由一个线程执行。请求“休眠”意味着你想让整个VM实例停止那么多(毫秒),我认为这在JavaScript世界中不是一个非常现实的要求,因为如果执行线程休眠,那么不仅是特定的函数,所有其他执行都会受到影响。

首先,不可能真正休眠该线程。你只能通过不做任何事情的方式来让线程保持忙碌。但是,如果您只想在某些计算中添加延迟,请将它们的执行放在单个函数上下文中,并让继续发生在该函数中的setTimeout(或Promise,如果您愿意)中。如果通过睡眠,你想要延迟一些事情,否则,这是不可能的。

其他回答

我会将setTimeOut封装在Promise中,以实现与其他异步任务的代码一致性:Fiddle中的Demo

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

它的用法如下:

sleep(2000).then(function() {
   // Do something
});

如果您习惯使用Promise,那么很容易记住语法。

一种非常简单的睡眠方式,它将与运行JavaScript的任何东西兼容。。。这段代码已经过500个条目的测试,CPU和内存的使用情况在我的web浏览器上仍然不可见。

这里有一个函数,它等待节点变为可见。。。

此函数创建一个新的上下文函数(){}以避免递归。我们在这个新上下文中放置了与调用者代码相同的代码。我们使用函数Timeout在几秒钟后调用我们的函数。

var get_hyper = function(node, maxcount, only_relation) {
    if (node.offsetParent === null) {
        // node is hidden
        setTimeout(function () { get_hyper(node, maxcount, only_relation)}, 
                   1000);
        return;
    };

    // Enter the code here that waits for that node becoming visible
    // before getting executed.

};

2021+更新

如果您正在寻找以下替代方案:

let sleep = ms => new Promise(res=>setTimeout(res,ms));

然后使用这个:

let sleep = async ms => void await Atomics.waitAsync(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms).value;

请注意,在发布此问题时,它是第3阶段提案。此外,它可能要求您的站点进行跨源隔离。要查看它在浏览器中是否有效,(在堆栈溢出上)请尝试以下操作:

let sleep=async ms=>void await Atomics.waitAsync(新Int32Array(新SharedArray Buffer(4)),0,0,ms).value;void异步函数(){console.log(1);等待睡眠(2000);console.log(2);}()

一行使用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();

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转换为生成器插件。