等到标志 =true

2022-08-30 04:42:32

我有这样的javascript函数:

function myFunction(number) {

    var x=number;
    ...
    ... more initializations
    //here need to wait until flag==true
    while(flag==false)
    {}

    ...
    ... do something

}

问题是javascript卡在一段时间内并卡住了我的程序。所以我的问题是,我如何在函数的中间等待,直到标志为真而不用“忙碌等待”?


答案 1

Javascript是单线程的,因此页面阻塞行为。您可以使用其他人建议的延迟/承诺方法。最基本的方法是使用 .例如:window.setTimeout

function checkFlag() {
    if(flag === false) {
       window.setTimeout(checkFlag, 100); /* this checks the flag every 100 milliseconds*/
    } else {
      /* do something*/
    }
}
checkFlag();

这是一个很好的教程,有进一步的解释:教程

编辑

正如其他人所指出的,最好的方法是重新构建代码以使用回调。但是,这个答案应该可以让您了解如何使用 “模拟” 异步行为。window.setTimeout


答案 2

因为浏览器中的javascript是单线程的(除了这里不涉及的webworker),并且javascript执行的一个线程在另一个线程可以运行之前运行完成,所以你的语句:

while(flag==false) {}

将简单地永远运行(或者直到浏览器抱怨无响应的javascript循环),页面将显示为挂起,并且没有其他javascript有机会运行,因此标志的值永远无法更改。

为了进一步解释,Javascript是一种事件驱动的语言。这意味着它运行一段Javascript,直到它将控制权返回给解释器。然后,只有当它返回到解释器时,Javascript才会从事件队列中获取下一个事件并运行它。

计时器和网络事件等所有内容都在事件队列中运行。因此,当计时器触发或网络请求到达时,它不会“中断”当前正在运行的Javascript。相反,一个事件被放入Javascript事件队列中,然后,当当前运行的Javascript完成时,下一个事件从事件队列中提取,轮到它运行。

因此,当您执行无限循环(例如 )时,当前正在运行的 Javascript 永远不会完成,因此下一个事件永远不会从事件队列中提取,因此 永远不会更改 的值。他们在这里的关键是Javascript不是中断驱动的。当计时器触发时,它不会中断当前正在运行的Javascript,运行其他Javascript,然后让当前运行的Javascript继续。它只是被放入事件队列中,等待当前运行的Javascript完成,轮到它运行。while(flag==false) {}flag


您需要做的是重新思考代码的工作原理,并找到一种不同的方法来触发值更改时要运行的任何代码。Javascript被设计为一种事件驱动的语言。因此,您需要做的是弄清楚您可以注册感兴趣的事件,以便您可以侦听可能导致标志更改的事件,并且可以检查该事件上的标志,或者您可以从任何可能更改标志的代码中触发自己的事件,或者您可以实现一个回调函数,无论该标志发生任何代码更改,只要该段,该代码都可以调用您的回调。负责更改标志值的代码会将其值更改为 ,它只调用回调函数,因此,当标志设置为时要运行的代码将在正确的时间运行。这比尝试使用某种计时器不断检查标志值要有效得多。flagtruetrue

function codeThatMightChangeFlag(callback) {
    // do a bunch of stuff
    if (condition happens to change flag value) {
        // call the callback to notify other code
        callback();
    }
}