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

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

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


当前回答

实际上,您可以使用与pausecomp函数相同的while循环实现sleep()(这基本上是相同的):

const sleep = (seconds) => {
    const waitUntil = new Date().getTime() + seconds * 1000
    while(new Date().getTime() < waitUntil) {
        // do nothing
    }
}

您可以像这样使用sleep()方法:

const main = () => {
    const a = 1 + 3

    // Sleep 3 seconds before the next action
    sleep(3)
    const b = a + 4

    // Sleep 4 seconds before the next action
    sleep(4)
    const c = b + 5
}

main()

这就是我想象你会使用睡眠功能的方式,而且读起来相对简单。我借鉴了另一篇文章《JavaScript中的睡眠——动作之间的延迟》,以展示您可能打算如何使用它。

不幸的是,你的电脑会变热,所有工作都会受阻。如果在浏览器中运行,该选项卡将停止,用户将无法与页面交互。

如果您将代码重组为异步的,那么您可以将setTimeout()作为与其他文章相同的睡眠函数。

// define sleep using setTimeout
const sleep = (seconds, callback) => setTimeout(() => callback(), seconds * 1000)

const main = () => {
    const a = 1 + 3
    let b = undefined
    let c = undefined

    // Sleep 3 seconds before the next action
    sleep(3, () => {
        b = a + 4

        // Sleep 4 seconds before the next action
        sleep(4, () => {
            c = b + 5
        })
    })
}

main()

正如你所说,这不是你想要的。我修改了Sleep in JavaScript中的示例-动作之间的延迟,以说明为什么会出现这种情况。当您添加更多动作时,要么需要将逻辑拉入单独的函数,要么将代码嵌套得越来越深(回调地狱)。

为了解决“回调地狱”,我们可以使用promise来定义睡眠:

const sleep = (seconds) => new Promise((resolve => setTimeout(() => resolve(), seconds * 1000)))

const main = () => {
    const a = 1 + 3
    let b = undefined
    let c = undefined

    // Sleep 3 seconds before the next action
    return sleep(3)
        .then(() => {
            b = a + 4

            // Sleep 4 seconds before the next action
            return sleep(4)
        })
        .then(() => {
            c = b + 5
        })
}

main()

Promise可以避免深度嵌套,但看起来仍然不像我们最初使用的常规同步代码。我们希望编写看起来同步的代码,但没有任何缺点。

让我们再次使用async/await重写我们的主方法:

const sleep = (seconds) => new Promise((resolve => setTimeout(() => resolve(), seconds * 1000)))

const main = async () => {
    const a = 1 + 3

    // Sleep 3 seconds before the next action
    await sleep(3)
    const b = a + 4

    // Sleep 4 seconds before the next action
    await sleep(4)
    const c = b + 5
}

main()

使用async/await,我们可以调用sleep(),就好像它是一个同步的阻塞函数一样。这解决了您可能在其他帖子中使用回调解决方案时遇到的问题,并避免了长时间循环的问题。

其他回答

我同意其他海报。忙着睡觉是个坏主意。

但是,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,以执行它排队的任何其他代码。

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

这会帮你的。

var reloadAfter = 10; //seconds
var intervalId = setTimeout(function() {
    //code you want to execute after the time waiting
}, reloadAfter * 1000); // 60000 = 60 sec = 1 min

如果确实要暂停脚本,可以执行以下操作:

var milliseconds;
var pretime;
var stage;

function step(time){
  switch(stage){
    case 0:
      //Code before the pause

      pretime=time;
      milliseconds=XXX;
      stage=1;
      break;
    case 1:
      //Code that is looped through while paused

      if(time-pretime >= milliseconds){
        //Code after the pause

        pretime=time;
        milliseconds=XXX;
        stage=2;
      }
      break;
    case 2:
      //Code that is looped through while paused

      if(time-pretime >= milliseconds){
        //Code after the pause

        pretime=time;
        milliseconds=XXX;
        stage=3;
      }
      break;
    case 3:
      //Etc...
  }

  Window.requestAnimationFrame(step)
}

step();

如果您使用循环,这可能正是您想要的,并且您可以以某种方式对其进行更改,从而获得伪多线程,其中一些函数等待一段时间,其他函数正常运行。我一直在纯JavaScript游戏中使用这个。

使用三种功能:

调用setInterval启动循环的函数一个函数,它调用clearInterval来停止循环,然后调用setTimeout来休眠,最后在setTimeout内调用作为回调来重新启动循环一个循环,跟踪迭代次数,设置睡眠次数和最大次数,一旦达到睡眠次数就调用睡眠函数,并在达到最大次数后调用clearInterval

var foo={};函数main(){“使用严格”;/*初始化全局状态*/foo.bar=foo.bar ||0;/*初始化计时器*/foo.bop=设置间隔(foo.baz,1000);}睡眠=功能(计时器){“使用严格”;clearInterval(计时器);timer=setTimeout(function(){main()},5000);};foo.baz=函数(){“使用严格”;/*更新状态*/foo.bar=数字(foo.bar+1)||0;/*日志状态*/console.log(foo.bar);/*检查状态并在10时停止*/(foo.bar===5)&&睡眠(foo.bop);(foo.bar==10)&&clearInterval(foo.bop);};main();

工具书类

使用JavaScript开发游戏为什么iOS 8中的滚动事件更改是一件大事Ember.js中的实时轮询系统使用requestAnimationFrame()驱动动画MDN:JavaScript并发模型和事件循环网格研究:Node.js在JavaScript中超过60fps第2部分:不阻塞单个线程的CPU密集型JavaScript计算

你可以这样做。所有函数都可以继承的休眠方法:

Function.prototype.sleep=函数(延迟,…args){setTimeout(()=>this(…args),delay)}console.log.sleep(2000年,“你好,世界!!”)