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

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

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


当前回答

这里大多数解决方案的问题是它们倒带堆栈。在某些情况下,这可能是一个大问题。在这个例子中,我展示了如何以不同的方式使用迭代器来模拟真实的睡眠。

在本例中,生成器正在调用自己的next(),因此一旦它启动,它就自己运行了。

var h = a();
h.next().value.r = h; // That's how you run it. It is the best I came up with

// Sleep without breaking the stack!!!
function *a(){
    var obj = {};

    console.log("going to sleep....2s")

    setTimeout(function(){obj.r.next();}, 2000)
    yield obj;

    console.log("woke up");
    console.log("going to sleep no 2....2s")
    setTimeout(function(){obj.r.next();}, 2000)
    yield obj;

    console.log("woke up");
    console.log("going to sleep no 3....2s")

    setTimeout(function(){obj.r.next();}, 2000)
    yield obj;

    console.log("done");
}

其他回答

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

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游戏中使用这个。

让事情看起来像大多数人想要的更好的解决方案是使用匿名函数:

alert('start');
var a = 'foo';
// Lots of code
setTimeout(function(){  // Beginning of code that should run AFTER the timeout
    alert(a);
    // Lots more code
}, 5000);  // Put the timeout here

这可能是最接近你想要的东西。

注意,如果你需要多次睡眠,这可能会在匆忙中变得很难看,你可能需要重新考虑你的设计。

对于希望将循环执行的一组调用隔开的特定情况,可以使用类似于下面代码的原型。如果没有原型,可以用setTimeout替换延迟函数。

function itemHandler(item)
{
    alert(item);
}

var itemSet = ['a','b','c'];

// Each call to itemHandler will execute
// 1 second apart
for(var i=0; i<itemSet.length; i++)
{
    var secondsUntilExecution = i;
    itemHandler.delay(secondsUntilExecution, item)
}

如果你想要比setTimeout和setInterval更简单的函数,你可以将它们包装在函数中,只需颠倒参数的顺序,给它们起个好听的名字:

function after(ms, fn){ setTimeout(fn, ms); }
function every(ms, fn){ setInterval(fn, ms); }

CoffeeScript版本:

after = (ms, fn)-> setTimeout fn, ms
every = (ms, fn)-> setInterval fn, ms

然后,您可以将它们很好地用于匿名函数:

after(1000, function(){
    console.log("it's been a second");
    after(1000, function(){
        console.log("it's been another second");
    });
});

现在它很容易读成“N毫秒后,…”(或“每N毫秒,…”)

在Firebug(可能还有其他JavaScript控制台)中,只有在指定的睡眠时间(…)之后,点击enter后才会发生任何事情

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

使用示例:

函数sleepFor(sleepDuration){var now=new Date().getTime();而(newDate().getTime()<now+sleepDuration){/*什么都不做*/}}函数sleepThenAt(){sleepFor(2000);console.log(“您好,JavaScript睡眠!”);}sleepThenAt()

注:仅用于调试和开发