调用setTimeout内部的函数未被调用

时间:2016-08-16 17:44:17

标签: javascript

我有一个小的JavaScript代码,其中我试图使用setTimeout等待一些外部输入到达(通过responseReceived变量),或等待最大阈值时间然后退出。

以下是代码:

var MAX_WAIT_THRESHOLD = 5000;
var keepWaiting = true;
var waitInterval = 500;
var totalTimeWaited = 0;

alert("Alert1");

while(keepWaiting == true) {
  setTimeout(function() {
    totalTimeWaited = totalTimeWaited + waitInterval;
    alert("Alert2");
    if(responseReceived == true || totalTimeWaited >= MAX_WAIT_THRESHOLD) {
      keepWaiting = false;
    }
  }, waitInterval);
}

问题是由于某种原因setTimeout(..)从未实际调用在其中创建的匿名函数。我通过在Chrome的JavaScript执行控件中放置断点来检查这一点,并且执行从未实际停止在匿名函数内的任何断点处。 JavaScript的执行不断在while ..行和setTimout(..)行之间切换。 responseReceived设置在代码的其他位置。另一种说法是第一个警报显示(Alert1),但第二个警告显示(Alert2)。

我做错了什么?

编辑:

我查看了报告的“重复”问题,但我看不出这与我的问题有什么关系。我的问题不在于while循环。而是关于为什么不调用内部匿名函数的原因。

2 个答案:

答案 0 :(得分:1)

您的代码终止了我的浏览器标签。 :d

为什么不直接使用setInterval并摆脱while循环?

var MAX_WAIT_THRESHOLD = 5000;
var waitInterval = 500;
var totalTimeWaited = 0;
var waiting = true;

alert("Alert1");

var interval = setInterval(function() {
    totalTimeWaited += waitInterval;
  alert("Alert2");
  if (responseReceived || totalTimeWaited >= MAX_WAIT_THRESHOLD) {
    // stop waiting
    clearInterval(interval);
    waiting = false;
    alert("Done");
  }
}, waitInterval);

答案 1 :(得分:0)

此问题与javascript concurrency model

有关

据我所知,所有setTimeout回调只能在while循环结束后执行,因为while循环是阻塞队列的消息。但在这种情况下,它永远不会结束。有另一个SO线程解释这个,但我现在无法找到它。

我看到你实际用控制变量控制循环的最大时间。但是,由于此控制代码位于setTimeout回调内,因此在循环结束之前不会将其推入队列,因此控制var keepWaiting在循环内永远不会变为false。如果您将该控制代码置于setTimeout函数之外,它将不会破坏浏览器并在某些时候显示“警报2”。消息 - 几次,实际上 - :

var MAX_WAIT_THRESHOLD = 5000;
var keepWaiting = true;
var waitInterval = 500;
var totalTimeWaited = 0;
var responseReceived = false;

console.log("Alert1");

while(keepWaiting == true) {
 setTimeout(function() {

console.log("Alert2");

}, waitInterval);

   totalTimeWaited = totalTimeWaited + waitInterval;
   if(responseReceived == true || totalTimeWaited >= MAX_WAIT_THRESHOLD) {
  keepWaiting = false;
    }   
}

然而,由于之前暴露的原因,所有回调都会在最后发生。

如果需要setTimeouts的永久循环,请使用递归而不是迭代。