等到 flag=trueflag、true

2023-09-08 09:36:57 作者:三分温柔七分坚强°

我有这样的javascript函数:

I have javascript function like this:

function myFunction(number) {

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

    ...
    ... do something

}

问题是javascript卡在while中并卡住了我的程序.所以我的问题是如何在没有忙等待"的情况下在函数中间等待直到标志为真?

The problem is that the javascript is stuck in the while and stuck my program. so my question is how can I wait in the middle of the function until flag is true without "busy-wait"?

推荐答案

因为浏览器中的 javascript 是单线程的(webworkers 除外,这里没有涉及),并且一个 javascript 执行线程在另一个线程运行之前运行完成,你的陈述:

Because javascript in a browser is single threaded (except for webworkers which aren't involved here) and one thread of javascript execution runs to completion before another can run, your statement:

while(flag==false) {}

将永远运行(或直到浏览器抱怨 javascript 循环无响应),页面将看起来被挂起,并且没有其他 javascript 将有机会运行,因此标志的值永远不会改变.

will simply run forever (or until the browser complains about a non-responsive javascript loop), the page will appear to be hung and no other javascript will ever get a chance to run, thus the flag's value can never be changed.

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

For a little more explanation, Javascript is an event driven language. That means that it runs a piece of Javascript until it returns control back to the interpreter. Then, only when it returns back to the interpreter, Javascript gets the next event from the event queue and runs it.

诸如计时器和网络事件之类的所有事物都通过事件队列运行.因此,当计时器触发或网络请求到达时,它永远不会中断"当前正在运行的 Javascript.相反,一个事件被放入 Javascript 事件队列,然后,当当前运行的 Javascript 完成时,从事件队列中拉出下一个事件并轮到它运行.

All things like timers and network events run through the event queue. So, when a timer fires or a network request arrives, it does not ever "interrupt" the currently running Javascript. Instead, an event gets put in the Javascript event queue and then, when the currently running Javascript finishes, the next event is pulled from the event queue and it gets its turn to run.

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

So, when you do an infinite loop such as while(flag==false) {}, the currently running Javascript never finishes and thus the next event is never pulled from the event queue and thus the value of flag never gets changed. They key here is that Javascript is not interrupt driven. When a timer fires, it does not interrupt the currently running Javascript, run some other Javascript and then let the currently running Javascript continue. It just gets put in the event queue waiting until the currently running Javascript is done to get its turn to run.

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

What you need to do is rethink how your code works and find a different way to trigger whatever code you want to run when the flag value changes. Javascript is designed as an event-driven language. So, what you need to do is figure out what events you can register an interest in so you can either listen for the event that might cause the flag to change and you can examine the flag on that event or you can trigger your own event from whatever code might change the flag or you can implement a callback function that whatever code changes that flag can call your callback whenever the piece of code responsible for changing the flag value would change it's value to true, it just calls the callback function and thus your code that wants to run when the flag gets set to true will get to run at the right time. This is much, much more efficient than trying to use some sort of timer to constantly check the flag value.

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