javascript settimeout永远不会触发函数并崩溃chrome

时间:2013-10-02 15:02:38

标签: javascript crash settimeout

此代码崩溃了chrome:

 var ms = 1000;

 function wait(ms) {

     function _done() {
         done = true;
         alert('timer: ' + timer + ', done: ' + done);
         clearTimeout(timer);
     }

     var done = false;
     var timer;
     alert('starting timer');
     while (!done) {
         timer = setTimeout(_done, ms);
     }
     alert('wait done');
 }

为什么呢?我该如何做到这一点?

3 个答案:

答案 0 :(得分:0)

当你在循环中设置timer变量时,循环不等待循环继续之前执行超时。

因此,每次循环发生时都会覆盖超时,并且代码永远不会执行,因为while循环运行代码的时间不会超过一秒。

请点击此处查看类似问题:Wait until a condition is true?

您的代码基本上会更改为以下内容:

var ms = 1000;
var done = false;
var timer;

function _done() {
    done = true;
    alert('timer: ' + timer + ', done: ' + done);
    clearTimeout(timer);
    wait(ms);
}

function wait(ms) {
    if(!done) {        
        alert('starting timer');
        timer = setTimeout(_done, ms);
    } else {
        //Is Done...
    }
}

一旦调用了wait函数,它将检查done变量是否为true,如果不是,它将调用_done函数将其设置为true。然后_done函数将重新调用wait函数以再次执行条件。

答案 1 :(得分:0)

这里有很多基本问题。

首先,我假设你的代码中没有描述某个地方,你实际上是通过传递wait来调用ms函数。

您希望在函数done中可以访问变量timer_done。为确保这一点,您应该在定义函数之前初始化变量。

setTimeout是异步的。 Javascript是单线程的,除非你不遗余力地启动其他线程(web worker)。 setTimeout不会冻结处理ms一段时间。它添加了一个事件,如果没有其他任何执行,它将运行。因为它没有阻塞,你的while循环将再次循环以创建另一个超时,另一个... ad infinium。由于其单线程特性,许多超时都不会中断while循环。它更像是Windows Message Queue。由于_done不会中断并将done设置为true,因此它会不断缩短越来越多的超时时间,直到不可避免的崩溃为止。

如果你想延迟一段时间的代码执行,那么你setTimeout一次,只要没有其他任何东西正在执行,执行就会在等待之后开始。

function _done() {
  alert('done!');
}

setTimeout(_done, 1000);

另一个注意事项,我不认为你已经超时clearTimeout已超时。它仅用于防止在超时之前发生超时。这意味着十分之九,您可以忽略setTimeout的返回值。

答案 2 :(得分:-1)

您缺少以下一行

timer = setTimeout(_done(), ms);

JSFIDDLE