Javascript sleep()函数提前执行

时间:2014-04-07 18:04:18

标签: javascript

我试图找出为什么在我的Code部分中,this.sleep(5000)似乎在我的绘制函数之前被调用,因为它在睡眠完成之前不会被绘制到画布。关于为什么这不符合我想要的方式的任何见解?

睡眠功能:

sleep: function(milliseconds) {
    setTimeout(function(){
        var start = new Date().getTime();
        while ((new Date().getTime() - start) < milliseconds){
        // Do nothing
        }
    },0);
},

代码:

var g = new Graph(this.diagram);
g.DrawPolygons(ctx,"blue");

this.sleep(5000);

3 个答案:

答案 0 :(得分:5)

您发布的代码存在一些问题。首先,您不应该使用while循环来暂停代码执行。

其次,您正在设置超时,允许其他代码在临时执行(是的,即使超时为零秒)。删除它,你应该能够暂停执行(但不要这样做):

sleep: function(milliseconds) {
    var start = new Date().getTime();
    while ((new Date().getTime() - start) < milliseconds){
      // Do nothing
    }
},

然而,占用JS线程意味着其他浏览器操作(重绘等)将暂停,直到您的睡眠功能退出。只需在JS文件中使用此代码就是反模式,您最好找到一种不同的方法来解决您的问题。阅读the XY problem并提出新问题。

如果您想要做的只是在某个时间间隔之后执行一些代码而不阻止其他所有内容,那么setTimeout就是您所需要的。

sleep: function(ms, funcToExecute) {
  setTimeout(funcToExecute, ms);
},

(虽然此时sleep是多余的)

答案 1 :(得分:5)

简短回答

不要这样做。 即使如果你开始工作,它也会不一致,会引起很多问题,而且几乎全球都被认为是不好的做法。

答案很长

JavaScript运行时几乎总是设计为be asynchronous。你的while循环旨在让一切......等等。你不能(或者至少不应该)在大多数JavaScript环境中这样做。

相反,安排事件/函数将来会执行一定数量的ms。这就是setTimeout的用途。这消除了对sleep功能的需要。

以下是应用上述更改后代码的外观:

var g = new Graph(this.diagram);
g.DrawPolygons(ctx, "blue");

setTimeout(function() {
    g.DrawPolygons(ctx, "red"); // Or whatever

    setTimeout(function() {
       g.DrawPolygons(ctx, "yellow"); // Or whatever

       // etc..
    }, 5000);
}, 5000);

ES2015更新 - 使用承诺

为避免潜在的深层嵌套setTimeout,您可以使用此

const sleep ms = new Promise(resolve => setTimeout(resolve,ms));

这只是一个在ms毫秒内解析的承诺。这允许您将所有内容保存在一个块中:

var g = new Graph(this.diagram);
g.DrawPolygons(ctx, "blue");

(async () => {
  g.DrawPolygons(ctx, "red");
  await sleep(5000);
  g.DrawPolygons(ctx, "yellow");
  await sleep(5000);
  // ...
})()

注意两件事:

  • 在引擎盖下,仍有事件/回调。它看起来像或Python的睡眠但行为的方式非常不同
  • 您只能在异步函数中使用它。有关详细信息,请参阅here

答案 2 :(得分:2)

这是因为JavaScript setTimeout的工作原理。当你这样做时:

setTimeout(function(){}, 0)

实际上告诉它在0ms之后运行该函数(最低值实际上是4ms,但除此之外)。您告诉它将来运行该功能。它实际上做的是将函数放在“堆栈的末尾”。它将完成运行调用它的函数,甚至可能在运行超时之前运行一些UI重绘。

如果此代码是在循环中运行的,那么当您认为它们将会> 时,您的超时将完全无法运行;)

另外,请记住JavaScript是单线程。一个线程运行您的代码以及UI重绘。执行无效的while循环并等待5秒 锁定浏览器。它将阻止任何用户交互和UI重绘。它甚至可能让操作系统认为浏览器崩溃了。不要这样做!

相反,尝试设置超时以在5000ms之后运行下一个多边形:

var g = new Graph(this.diagram);
g.DrawPolygons(ctx,"blue");

setTimeout(function(){
    // Code to run after the "sleep"

    // Maybe another shape
    g.DrawPolygons(ctx, "red");
}, 5000);