sleep()的 JavaScript 版本是什么?

是否有比下面的pausecomp函数( 从此处获取 )更好的方法来设计 JavaScript 的sleep

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

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

答案

2017 年— 2019 年更新

自 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. 只有在以async关键字为前缀的函数中或在某些环境中(例如,Chrome DevTools 控制台或 Runkit)在脚本的顶层执行await
  2. await只会暂停当前的async功能

两个新的 JavaScript 功能帮助编写了此 “睡眠” 功能:

兼容性

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

(请参阅2016 年更新的答案

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

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

因此,您几乎完全可以遵循别人的建议 - 您需要将代码分解为多个功能。

那么,您的问题是一个错误的选择。您无法以自己想要的方式入睡,也不应追求您建议的解决方案。

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

每当我想在函数中间睡觉时,我都会重构为使用setTimeout()

编辑

在任何语言中臭名昭著的睡眠或延迟功能都引起了很大的争议。有些人会说应该总是有一个信号或回调来触发给定的功能,另一些人则认为有时任意的延迟时间是有用的。我说,在这个行业中,对每个人来说,一条规则永远不能决定任何事情。

编写睡眠函数非常简单,并且可以在 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!
});

仅用于 debug / dev ,如果对某人有用,我将其发布

有趣的是,在 Firebug(可能还有其他 js 控制台)中,仅在指定的睡眠持续时间之后,按 Enter 键之后什么也没有发生(...)

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

使用示例:

function sleepThenAct(){ sleepFor(2000); console.log("hello js sleep !"); }

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

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

做到这一点的方法是将您的功能分解为前后各部分。

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

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

确保您的函数名称仍然准确地描述每个部分的功能(IE GatherInputThenWait 和 CheckInput,而不是 funcPart1 和 funcPart2)

编辑

这种方法的目的是直到超时后才执行您决定的代码行,同时仍将控制权交还给客户端 PC 来执行排队的其他内容。

进一步编辑

正如评论中指出的那样,这绝对不会循环工作。您可以进行一些怪异的(丑陋的)黑客攻击,使其循环运行,但总的来说,这只会造成灾难性的意大利面条式代码。

出于对 $ DEITY 的热爱,请不要进行繁忙的睡眠功能。 setTimeoutsetInterval您的所有需求。

var showHide = document.getElementById('showHide');
setInterval(() => {
    showHide.style.visibility = "initial";
    setTimeout(() => {
        showHide.style.visibility = "hidden"
    }, 1000);
    ;
}, 2000);
<div id="showHide">Hello! Goodbye!</div>

每两秒钟间隔将文本隐藏一秒钟。这显示了如何使用 setInterval 和 setTimeout 每秒显示和隐藏文本。

我知道这是一个古老的问题,但是如果(像我一样)您在 Rhino 中使用 Javascript,则可以使用...

try
{
  java.lang.Thread.sleep(timeInMilliseconds);
}
catch (e)
{
  /*
   * This will happen if the sleep is woken up - you might want to check
   * if enough time has passed and sleep again if not - depending on how
   * important the sleep time is to you.
   */
}

如果您使用的是 jQuery,则实际上有人创建了一个 “延迟” 插件,该插件不过是 setTimeout 的包装器:

// Delay Plugin for jQuery
// - http://www.evanbot.com
// - © 2008 Evan Byrne

jQuery.fn.delay = function(time,func){
    this.each(function(){
        setTimeout(func,time);
    });

    return this;
};

然后,您可以按预期在一行函数调用中使用它:

$('#warning')
.addClass('highlight')
.delay(1000)
.removeClass('highlight');

我也搜索了睡眠解决方案(不是用于生产代码,仅用于开发 / 测试),并找到了这篇文章:

http://narayanraman.blogspot.com/2005/12/javascript-sleep-or-wait.html

... 这是客户端解决方案的另一个链接: http : //www.devcheater.com/

同样,当您调用alert() ,您的代码也会被暂停,同时显示警报 - 需要找到一种不显示警报但获得相同效果的方法。 :)

这是使用同步 XMLHttpRequest 的简单解决方案:

function sleep(n){
  var request = new XMLHttpRequest();
  request.open('GET', '/sleep.php?n=' + n, false);  // `false` makes the request synchronous
  request.send(null);
}

sleep.php 的内容:

<?php sleep($_GET['n']);

现在调用它:sleep(5);