我有这样的javascript函数:
function myFunction(number) {
var x=number;
...
... more initializations
//here need to wait until flag==true
while(flag==false)
{}
...
... do something
}
问题是javascript卡在while中并卡住了我的程序。所以我的问题是如何在函数中间等待,直到标志为真而没有“忙等待”?
原文由 ilay zeidman 发布,翻译遵循 CC BY-SA 4.0 许可协议
因为浏览器中的 javascript 是单线程的(此处未涉及的 webworkers 除外),并且一个 javascript 执行线程在另一个线程可以运行之前运行到完成,所以您的声明:
将永远运行(或直到浏览器抱怨无响应的 javascript 循环),页面将似乎被挂起,并且没有其他 javascript 将有机会运行,因此标志的值永远不会改变。
稍微解释一下, Javascript 是一种事件驱动语言。这意味着它会运行一段 Javascript,直到将控制权返回给解释器。然后,只有当它返回解释器时,Javascript 从事件队列中获取下一个事件并运行它。
诸如计时器和网络事件之类的所有事物都通过事件队列运行。因此,当计时器触发或网络请求到达时,它永远不会“中断”当前正在运行的 Javascript。取而代之的是,一个事件被放入 Javascript 事件队列,然后,当当前运行的 Javascript 完成时,从事件队列中提取下一个事件并轮到它运行。
因此,当您执行诸如
while(flag==false) {}
之类的无限循环时,当前运行的 Javascript 永远不会完成,因此下一个事件永远不会从事件队列中拉出,因此flag
的值永远不会改变。他们的关键是 Javascript 不是中断驱动的。当计时器触发时,它不会中断当前正在运行的 Javascript,而是运行其他一些 Javascript,然后让当前正在运行的 Javascript 继续。它只是被放入事件队列中,等待当前运行的 Javascript 完成以轮到它运行。你需要做的是重新考虑你的代码是如何工作的,并找到一种不同的方式来触发你想要在
flag
值更改时运行的任何代码。 Javascript 被设计为一种事件驱动的语言。因此,您需要做的是找出您可以注册感兴趣的事件,以便您可以侦听可能导致标志更改的事件,您可以检查该事件的标志,或者您可以触发您自己的事件任何代码可能会更改标志,或者您可以实现一个回调函数,无论何时更改该标志的代码都可以调用您的回调,只要负责更改标志值的代码将其值更改为true
,它只会调用回调函数,因此您的想要在标志设置为true
时运行的代码将在正确的时间运行。这比尝试使用某种计时器来不断检查标志值要有效得多。