sleep() 的 JavaScript 版本是什么?

IT技术 javascript sleep
2020-12-12 23:31:20

有没有sleep比以下pausecomp函数(取自此处更好的在 JavaScript 中设计 a 的方法

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

这不是JavaScriptSleep的副本- 动作之间的延迟我想要在函数中间真正休眠,而不是在一段代码执行之前延迟。

6个回答

2017 — 2021 更新

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

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

async function demo() {
  console.log('Taking a break...');
  await sleep(2000);
  console.log('Two seconds later, showing sleep in a loop...');

  // Sleep in loop
  for (let i = 0; i < 5; i++) {
    if (i === 3)
      await sleep(2000);
    console.log(i);
  }
}

demo();

就是这个。await sleep(<duration>).

或者作为单线:

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

注意,

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

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

兼容性

如果您正在使用节点年纪比7(已经达成了一些奇怪的原因生命的尽头),或瞄准旧的浏览器,async/await仍然可以通过使用巴别塔(一种工具,将transpile的JavaScript +新功能集成到普通的旧的JavaScript) , 与transform-async-to-generator插件。

当前浏览器对此的支持是什么?在绝大多数浏览器或至少所有常见浏览器支持此解决方案之前,我不会认为以前的解决方案是“过时的”。相反,我认为这个解决方案有趣但不可用/不切实际,直到它得到广泛支持。
2021-02-06 23:31:20
@jacroe - 转译器处理箭头函数以及 async/await(无论如何都会导致 IE 吐血)
2021-02-06 23:31:20
@AlvinThompson:大多数现代 Web 开发都使用转译器,因此原生浏览器支持比更干净、更面向未来的代码更重要。无论如何,请参阅caniuse
2021-02-09 23:31:20
这里的好东西。我想知道,在 JS 调用“睡眠”模式后,这如何影响或与现代浏览器的“活动”/“非活动”状态相关联?浏览器是否可以像一般 JS 预期的那样阻止睡眠,以便稍后在变为“活动”时回忆,或者它是否有不同的行为?
2021-03-02 23:31:20
单线 await new Promise(r => setTimeout(() => r(), 2000));
2021-03-04 23:31:20

(请参阅2016 年更新答案

我认为想要执行一个动作,等待,然后执行另一个动作是完全合理的。如果您习惯于使用多线程语言进行编写,那么您可能会想到让执行一段时间,直到您的线程唤醒。

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

因此,您几乎无法接受其他人的建议——您需要将代码分解为多个函数。

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

睡眠可以在 JavaScript 中完美实现,尽管不是实时精度。毕竟它是一个基于事件的系统。如果异步调用完成,则触发事件。我认为没有理由在发出 sleep() 之后,将控制权返回给浏览器,直到睡眠结束,将控制权返回给调用函数时,为什么不能执行相同的操作。是的,我也同意有时候睡觉是很方便的,特别是当开发人员在你把设计搞砸之前你没有其他出路,除了你没有时间完全重构之外
2021-02-08 23:31:20
我同意为什么sleep()在 JS 中不可能,而且大多数时候有更好的方法来做事。但我仍然认为引擎将所有东西联系在一起的方式是设计缺陷;如果没有sleep()引擎破坏 CPU 并像疯子一样冻结应用程序,语言没有理由不能将功能限制为特定的脚本、页面或功能。现在是 2015 年,您不应该使用while(1). 我们有 Flash 来处理这样的事情。
2021-02-10 23:31:20
试试催眠,它遵循这个想法:coolwanglu.github.io/hypnotic/web/demo.html
2021-02-16 23:31:20
这根本不是一个正确的答案。如果 Javascript 没有睡眠功能,那只是因为 ECMAScript 不需要它。它是负责 Javascript 设计的机构的设计选择。本来可以让 Javascript 运行时在运行下一行代码之前等待给定的时间,但它被选择不这样做。
2021-02-17 23:31:20
在一种情况下,无论您重构多少,超时都不能解决问题:如果您在服务器端运行,则客户端正在等待数据,而您无法直接访问到将其传递给超时回调。例如,在meteor 中,您可以在一个方法中运行。在这种情况下,您应该考虑使用未来,如下所述:stackoverflow.com/questions/12569712/...
2021-03-06 23:31:20

在 JavaScript 中,我重写了每个函数,以便它可以尽快结束。您希望浏览器重新获得控制权,以便它可以更改您的 DOM。

每次我想在我的函数中间睡一会时,我都会重构以使用setTimeout().

编辑

任何语言中臭名昭著的睡眠或延迟功能都备受争议。有些人会说应该总是有一个信号或回调来触发给定的功能,其他人会争辩说有时任意的延迟时刻是有用的。我说,每个人都有自己的规则,在这个行业中,一个规则永远不能决定任何事情。

编写 sleep 函数很简单,而且使用 JavaScript Promises 使其更有用:

// sleep time expects milliseconds
function sleep (time) {
  return new Promise((resolve) => setTimeout(resolve, time));
}

// Usage!
sleep(500).then(() => {
    // Do something after the sleep!
});
@Tim 循环安全版本: for(i=0; i<5; i++) { (function(i) { setTimeout(function() { console.log(i); }, 1000*i); })(i); }
2021-02-12 23:31:20
@EugenioMiró 如果代码不打算在网页中使用,请让主机的对象模型实现 sleep 方法。-- 我认为这个问题是针对 DOM 的,它暴露在网页上运行的 javascript 中。
2021-02-16 23:31:20
@Nosredna 是的,我们了解如何进行异步调用,这对我们 sleep() 没有帮助。我希望我的调用按特定顺序进行,并按特定顺序返回数据。我在 for 循环中有 5 个级别。我想阻止执行。真正的睡眠方法不会“减慢浏览器的速度”,睡眠手控制回到浏览器和任何其他需要 CPU 时间的线程,同时它仍处于阻塞状态。
2021-02-17 23:31:20
通过关闭方式。 function foobar(el) { setTimeout(function() { foobar_cont(el); }, 5000); }
2021-02-23 23:31:20
好的,如果代码不打算在网页中使用怎么办?
2021-03-07 23:31:20

Firebug(可能还有其他 JavaScript 控制台)中,按下 Enter 后什么也不会发生,只有在指定的睡眠持续时间之后 (...)

function sleepFor(sleepDuration){
    var now = new Date().getTime();
    while(new Date().getTime() < now + sleepDuration){ /* Do nothing */ }
}

使用示例:

function sleepFor(sleepDuration){
    var now = new Date().getTime();
    while(new Date().getTime() < now + sleepDuration){ 
        /* Do nothing */ 
    }
}

function sleepThenAct(){
    sleepFor(2000);
    console.log("Hello, JavaScript sleep!");
}

sleepThenAct()

注意:仅用于调试和开发

这不是一个答案。它与问题中的代码完全相同,只是略短。
2021-02-08 23:31:20
永远不要这样做。这将使 CPU 在它执行的核心上达到 100% 并阻止它。
2021-02-10 23:31:20
@mafu 这就是为什么它说only for debug/dev... rolleyes
2021-02-12 23:31:20
这很有用,而且可能是命令行 javascript 应用程序中唯一的睡眠方式,因为 async/await 没有帮助。
2021-02-21 23:31:20
忙着等待,真的吗?在 JS 中?几秒钟?如果我发现一个网站这样做,它将被阻止。
2021-02-22 23:31:20

我同意其他海报。忙碌的睡眠只是一个坏主意。

但是, setTimeout 不会阻止执行。它在超时设置后立即执行函数的下一行,而不是在超时到期后,因此不会完成睡眠将完成的相同任务。

这样做的方法是将您的功能分解为前后部分。

function doStuff()
{
  // Do some things
  setTimeout(continueExecution, 10000) // Wait ten seconds before continuing
}

function continueExecution()
{
   // Finish doing things after the pause
}

确保您的函数名称仍然准确地描述了每个部分在做什么(即 GatherInputThenWait 和 CheckInput,而不是 funcPart1 和 funcPart2)

此方法实现的目的是,直到超时后才执行您决定的代码行,同时仍将控制权返回给客户端 PC 以执行它已排队的其他任何内容。

正如评论中指出的那样,这绝对不会在循环中工作你可以做一些花哨的(丑陋的)hacking 让它在循环中工作,但总的来说,这只会导致灾难性的意大利面条式代码。

-1 为此。同样,这不能回答问题。这更像是“如何异步执行函数”之类的问题的答案,这与“如何阻止代码执行”有很大不同。
2021-02-13 23:31:20
@Alexander当然可以,因为 setTimeout() 的目的是通过异步运行代码来防止浏览器锁定。console.log()里面foo_continue()放在 setTimeout 版本中,你会得到相同的结果。
2021-02-13 23:31:20
是的。当您有循环或嵌套循环时,这会变得棘手。你必须放弃你的 for 循环,取而代之的是计数器。
2021-02-25 23:31:20
触摸。我的意思是,这仍然是可能的,但在那种情况下是丑陋和骇人听闻的。你也可以使用一些静态的布尔状态变量,但这也很hackish。
2021-02-27 23:31:20
@Nosredna 不,您会使用闭包。例如: function foo(index) { setTimeout(function() { foo_continue(index); }, 10000); }and for(var X = 0; X < 3;X++) { foo(X); }- X被传递到foo,然后在最终被调用index在名称下重用foo_continue
2021-03-03 23:31:20