我有一个小的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
循环。而是关于为什么不调用内部匿名函数的原因。
答案 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的永久循环,请使用递归而不是迭代。