什么是 sleep() 的 JavaScript 版本?

2022-08-29 21:47:54

有没有比以下函数(从这里获取)更好的方法来设计JavaScript?sleeppausecomp

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

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


答案 1

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));

将其用作:

await sleep(<duration>);

演示:

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

async function demo() {
    for (let i = 0; i < 5; i++) {
        console.log(`Waiting ${i} seconds...`);
        await sleep(i * 1000);
    }
    console.log('Done');
}

demo();

请注意,

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

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

  • Promises,ES2015(又名ES6)的原生功能。我们还在睡眠函数的定义中使用箭头函数。
  • async/await 功能允许代码显式等待承诺结算(解析或拒绝)。

兼容性

如果由于某种原因,您使用的是早于7的Node(在2017年达到生命周期结束),或者针对旧的浏览器,/仍然可以通过Babel(一种将JavaScript +新功能转换为普通旧JavaScript的工具)使用,并使用transform-async-to-generator插件。asyncawait


答案 2

(请参阅 2016 年的更新答案)

我认为想要执行一个操作,等待,然后执行另一个操作是完全合理的。如果您习惯于用多线程语言编写,那么您可能有在设定的时间内产生执行的想法,直到线程唤醒。

这里的问题是JavaScript是一个基于单线程事件的模型。虽然在特定情况下,让整个引擎等待几秒钟可能会很好,但总的来说,这是不好的做法。假设我想在编写自己的函数时使用您的函数?当我调用你的方法时,我的方法会全部冻结。如果JavaScript可以以某种方式保留函数的执行上下文,将其存储在某个地方,然后将其恢复并稍后继续,那么睡眠可能会发生,但这基本上是线程。

所以你几乎被别人的建议所困住了 - 你需要将你的代码分解成多个函数。

那么,你的问题有点错误的选择。没有办法以你想要的方式睡觉,你也不应该追求你建议的解决方案。