Javascript Anonymous Functions and Global Variables

I thought I would try to be smart and create my own Wait function (I understand that there are other ways to do this). Therefore, I wrote:

var interval_id; var countdowntimer = 0; function Wait(wait_interval) { countdowntimer = wait_interval; interval_id = setInterval(function() { --countdowntimer <=0 ? clearInterval(interval_id) : null; }, 1000); do {} while (countdowntimer >= 0); } // Wait a bit: 5 secs Wait(5); 

It all works, except for an infinite loop. After checking, if I take the While loop, the anonymous function is introduced 5 times, as expected. Thus, the global variable countdowntimer is reduced.

However, if I check the value of countdowntimer , in the While loop it never drops. This is despite the fact that the anonymous function is called during the While!

Clearly there are two countdowntimer values, but why?

EDIT

Ok, so I understand (now) that Javascript is single-threaded. And that - sort of - answers my question. But at what point in processing this single thread does the so-called asynchronous call using setInterval really happen? Is it just between function calls? Surely not, what about functions that take a lot of time?

+4
source share
4 answers

There are no two copies of the variable lying around. Javascript in web browsers is single-threaded (unless you are using new material for webmasters ). Thus, an anonymous function will never work, because Wait binds the interpreter.

You cannot use lively wait features in a Javascript browser; nothing else (and this is a bad idea in most other environments, even where they are possible). You should use callbacks instead. Here's a minimalist rework of this:

 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 

Edit Answering a question:

But at what point in processing this single thread does the so-called asynchronous call using setInterval really happen? Is it just between function calls? Surely not, what about functions that take a lot of time?

Quite a lot, yes - and therefore it is important that the functions are not lengthy. (Technically, this is not even between function calls, if you have a function that calls three other functions, the interpreter cannot do anything while this (external) function is running.) The interpreter essentially maintains a queue of functions that it needs to fulfill. It starts with the execution of any global code (rather, as a call to a large function). Then, when something happens (user input events, time for calling a callback scheduled through setTimeout been reached, etc.), the Interpreter pushes the calls that it must make to the queue. It always processes the call in front of the queue, and therefore things can stack up (for example, your setInterval calls, although setInterval is the special bit - it will not stop the subsequent callback if the previous one is still waiting in the queue). So think about when your code takes control and when it releases control (for example, upon return). The interpreter can only perform other actions after you release control and before he returns you again. And again, in some browsers (e.g. IE) the same stream is also used to draw the user interface, etc. Therefore, DOM inserts (for example) will not be displayed until you release the control back to the browser so that he could get while doing his painting.

When Javascript is in web browsers, you really need to take an event-oriented approach to developing and coding your solutions. A classic example tells the user information. In a non-event driven world, you can do this:

 // 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(); 

This does not work in an event driven world. Instead, you do the following:

 askTheQuestion(); setCallbackForQuestionAnsweredEvent(doSomethingWithAnswer); // If we had code here, it would happen *immediately*, // it wouldn't wait for the answer 

So, for example, askTheQuestion can impose a div on a page with fields offering the user various pieces of information with an OK button so that they can click when they are done. setCallbackForQuestionAnswered will indeed hook the click event to the OK button. doSomethingWithAnswer will collect information from the fields, delete or hide the div, and do something with the information.

+5
source

Most Javascript implementations are single-threaded , so when it executes a while , it doesn't allow anything to be done, so interval never starts while while working, thereby creating an infinite loop.

There are many similar attempts to create a sleep / wait / pause function in javascript, but since most implementations are single-threaded, it simply does not allow you to do anything during sleep (!).

An alternative way to make a delay is to write timeouts . They may delay the execution of a piece of code, but you will have to break it into many functions. You can always use the built-in functions to make tracking easier (and exchange variables in the same execution context).

There are also some libraries that add some syntactic advar to javascript, making it more readable.

EDIT: There's an excellent John Resig blog post about How javascript timers work . He largely explains this in detail. Hope this helps.

+3
source

In fact, it almost guaranteed that the interval function would never work while the loop was doing, since javascript is single-threaded.

There is a reason that no one has done Wait before (and many have tried); it just can't be done.

You will have to resort to the inhibition of your function in bits and schedule them using setTimeout or setInterval.

 //first part ... setTimeout(function(){ //next part }, 5000/*ms*/); 

Depending on your needs, this can (should) be implemented as a state machine.

+2
source

Instead of using the global variable countdowntimer, why not just change the millisecond attribute to setInterval? Sort of:

 var waitId; function Wait(waitSeconds) { waitId= setInterval(function(){clearInterval(waitId);}, waitSeconds * 1000); } 
0
source

Source: https://habr.com/ru/post/1310119/


All Articles