周围没有变量的两个副本。网络浏览器中的 Javascript 是单线程的(除非你使用新的网络工作者东西)。所以匿名函数永远没有机会运行,因为Wait
它占用了解释器。
您不能在基于浏览器的 Javascript 中使用忙等待功能;不会发生其他任何事情(而且在大多数其他环境中,即使在可能的情况下,它们也是一个坏主意)。您必须改用回调。这是一个极简主义的改造:
var interval_id;
var countdowntimer = 0;
function Wait(wait_interval, callback) {
countdowntimer = wait_interval;
interval_id = setInterval(function() {
if (--countdowntimer <=0) {
clearInterval(interval_id);
interval_id = 0;
callback();
}
}, 1000);
}
// Wait a bit: 5 secs
Wait(5, function() {
alert("Done waiting");
});
// Any code here happens immediately, it doesn't wait for the callback
编辑回答您的后续行动:
但是,在这个单线程的处理过程中,使用 setInterval 的所谓异步调用真的发生了吗?它只是在函数调用之间吗?当然不是,那些需要很长时间才能执行的功能呢?
差不多,是的——所以重要的是函数不能长时间运行。(从技术上讲,它甚至不在函数调用之间,因为如果你有一个调用其他三个函数的函数,解释器在该(外部)函数运行时不能做任何其他事情。)解释器基本上维护它需要的函数队列执行。它从执行任何全局代码开始(更像是一个大函数调用)。然后,当事情发生时(用户输入事件,到达调用调度回调的时间setTimeout
等),解释器将它需要进行的调用推送到队列中。它总是在队列的前面处理调用,所以事情可以堆积起来(就像你的调用setInterval
一样,虽然setInterval
有点特殊——如果前一个回调仍在队列中等待处理,它不会排队后续回调)。因此,请考虑您的代码何时获得控制权以及何时释放控制权(例如,通过返回)。口译员只能在您释放控制权并再次将控制权交还给您之前执行其他操作。同样,在某些浏览器(例如 IE)上,相同的线程也用于绘制 UI 等,因此 DOM 插入(例如)不会显示,直到您将控制权释放回浏览器以便它可以获取继续画它。
在 Web 浏览器中使用 Javascript 时,您确实需要采用事件驱动的方法来设计和编码您的解决方案。典型的例子是提示用户输入信息。在非事件驱动的世界中,您可以这样做:
// Non-functional non-event-driven pseudo-example
askTheQuestion();
answer = readTheAnswer(); // Script pauses here
doSomethingWithAnswer(answer); // This doesn't happen until we have an answer
doSomethingElse();
这在事件驱动的世界中是行不通的。相反,你这样做:
askTheQuestion();
setCallbackForQuestionAnsweredEvent(doSomethingWithAnswer);
// If we had code here, it would happen *immediately*,
// it wouldn't wait for the answer
因此,例如,askTheQuestion
可能会在页面上覆盖一个 div,其中包含提示用户输入各种信息的字段,并带有一个“确定”按钮,供他们在完成后单击。setCallbackForQuestionAnswered
真的会click
在“确定”按钮上挂钩事件。doSomethingWithAnswer
将从字段中收集信息,删除或隐藏 div,并对信息做一些事情。