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
}
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"?
Solution using Promise, async\await and EventEmitter which allows to react immediate on flag change without any kind of loops at all
EventEmitter
is builtin in node. In browser you shall need to include it by your own, for example using this package: https://www.npmjs.com/package/eventemitter3Because 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:
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.
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.
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.
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 offlag
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.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 totrue
, it just calls the callback function and thus your code that wants to run when the flag gets set totrue
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.With Ecma Script 2017 You can use async-await and while together to do that And while will not crash or lock the program even variable never be true
Modern solution using Promise
myFunction()
in the original question can be modified as followswhere
until()
is this utility functionSome references to async/await and arrow functions are in a similar post: https://stackoverflow.com/a/52652681/209794
ES6 with Async / Await ,