23.07.2020

SetTimeOut and SetInterval which is better to use in JavaScript? Timers in Javascript (setInterval, setTimeout) Parameters for function and context


  • From:
  • Registered: 2014.07.08
  • Posts: 3,896
  • Likes: 497

Topic: SetTimeOut and SetInterval, which is better to use in JavaScript?

To repeatedly run the code at regular intervals, the function setInterval. Nevertheless, it has a number of disadvantages, mainly this is a different behavior in different browsers.

The first difference is the difference in the timer setting for the next run. Let's create a small test: we will measure the amount of time that has passed since the start of the previous run and from its end.

var d1 = new Date(), d2 = new Date(); setInterval(function() ( var d = new Date(); document.body.innerHTML += (d - d1) + " " + (d - d2) + "
"; // Put a label at the beginning of the function d1 = new Date(); while (new Date() - d1< 200); // ничего не делаем 200 миллисекунд // И в конце функции d2 = new Date(); }, 1000);

The output will be informative starting from the second line.

In Firefox, Opera, Safari and Chrome, the situation will be similar: the first number will be approximately equal to 1000, the second - 200 less. The difference will only be in the spread of values. The smallest spread in Chrome and Opera.

2 Reply by PunBB (edited by PunBB 2017.06.08 16:45)

  • From: Moscow, Sovkhoznay 3, apt. 98
  • Registered: 2014.07.08
  • Posts: 3,896
  • Likes: 497

Another difference, less noticeable and more difficult to reproduce, but sometimes capable of causing a lot of trouble, is resistance to changes in the system time. If you run the following test

setInterval(function() ( document.body.innerHTML = Math.random(); ), 500);

And after starting, translate the system time back a minute, then in the Firefox and Safari browsers, the change of numbers will stop, and in a minute it will start again. Of course, manual translation of the system time is an extremely rare situation, but many systems are configured to automatically synchronize time with servers on the Internet, so in some situations this factor cannot be discounted.

Another small minus of the setInterval function is that in order to be able to stop its action, you need to remember its identifier somewhere, which is not always convenient.

3 Reply by PunBB

  • From: Moscow, Sovkhoznay 3, apt. 98
  • Registered: 2014.07.08
  • Posts: 3,896
  • Likes: 497

Re: SetTimeOut and SetInterval, which is better to use in JavaScript?

To get rid of the listed shortcomings of setInterval, you can use multiple setTimeout.

An important alternative to setInterval is the recursive setTimeout:

/** instead of: var timerId = setInterval(function() ( alert("tick"); ), 2000); */ var timerId = setTimeout(function tick() ( alert("tick"); timerId = setTimeout(tick, 2000); ), 2000);

In the code above, the next execution is scheduled immediately after the previous one finishes.

The recursive setTimeout is a more flexible timing method than setInterval, since the time until the next execution can be scheduled differently, depending on the results of the current one.

For example, we have a service that polls the server every 5 seconds for new data. If the server is overloaded, you can increase the polling interval to 10, 20, 60 seconds ... And then return it back when everything is back to normal.

If we regularly run processor-loading tasks, then we can estimate the time spent on their execution and plan the next launch earlier or later.

4 Reply by PunBB

  • From: Moscow, Sovkhoznay 3, apt. 98
  • Registered: 2014.07.08
  • Posts: 3,896
  • Likes: 497

Re: SetTimeOut and SetInterval, which is better to use in JavaScript?

Recursive setTimeout guarantees a pause between calls, setInterval does not.

Let's compare two codes. The first one uses setInterval:

var i = 1; setInterval(function() ( func(i); ), 100);

The second one uses a recursive setTimeout:

var i = 1; setTimeout(function run() ( func(i); setTimeout(run, 100); ), 100);

With setInterval , the internal timer will fire exactly every 100ms and call func(i):

The real pause between func calls with setInterval is less than specified in the code!

This is natural, because the running time of the function is not taken into account in any way, it "eats" part of the interval.

It is also possible that func turned out to be more complicated than we expected and took longer than 100 ms.

In this case, the interpreter will wait for the function to complete, then check the timer and, if the time to call setInterval has already come up (or passed), then the next call will occur immediately.

If the function is executed longer than the setInterval pause, then the calls will occur without any interruption at all.

5 Reply by sempai

  • From: Jerusalem
  • Registered: 2015.06.02
  • Posts: 958
  • Likes: 274

Re: SetTimeOut and SetInterval, which is better to use in JavaScript?

Everything depends on the task at hand. Initially, SetTimeOut is used to start the timer once, and SetInterval is used to start the loop. But both functions can be used to cycle through scripts, if, for example, run recursively in the SetTimeOut function, then it will act practically similarly to SetInterval.

The minus of SetInterval at the moment is that it does not take into account the execution time of the script (function) itself, and if, for example, you use it for heavy requests, then the interval time will be significantly reduced, and it may differ in different browsers.

But again, I repeat, if the function or request is minimized, then end user hardly feel the difference.
Therefore, what to use, everyone decides for himself.

It is extremely important to understand how JavaScript timers work. Often their behavior does not coincide with our intuitive perception of multithreading, and this is due to the fact that they actually run on the same thread. Let's look at four functions with which we can control timers:

  • var id = setTimeout(fn, delay); - Creates a simple timer that will call given function after a given delay. The function returns a unique ID with which the timer can be paused.
  • var id = setInterval(fn, delay); - Similar to setTimeout, but continuously calls the function at a given interval (until it is stopped).
  • clearInterval(id); clearTimeout(id); - Accepts a timer ID (returned by one of the functions described above) and stops callback"a from executing.
The main idea to consider is that the accuracy of the timer delay period is not guaranteed. To begin with, the browser executes all asynchronous JavaScript events on a single thread (such as mouse clicks or timers) and only at the time that the event's turn is due. This is best illustrated by the following diagram:

There is quite a lot of information in this figure that needs to be digested, but understanding this will give you a deeper understanding of how JavaScript asynchronous execution works. this chart represents time in milliseconds vertically, the blue boxes show blocks of JavaScript code that has been executed. For example, the first block executes in an average of 18ms, a mouse click blocks execution for approximately 11ms, and so on.

JavaScript can only execute one piece of code (due to the single-threaded nature of execution), each blocking the execution of other asynchronous events. This means that when an asynchronous event occurs (such as a mouse click, a timer is called, or an XMLHttp request completes), it is added to a queue and executed later (implementation varies by browser, of course, but let's call it a "queue") .

To begin with, let's imagine that two timers start inside the JavaScript block: setTimeout with a delay of 10ms and setInterval with the same delay. Depending on when the timer starts, it will fire at a time when we have not yet completed the first block of code. Note, however, that it does not fire immediately (this is not possible due to single-threading). Instead, the deferred function is queued and executed at the next available moment.

Also, during the execution of the first JavaScript block, a mouse click occurs. The handler for this asynchronous event (and it is asynchronous, because we cannot predict it) cannot be executed directly at this moment, so it also gets queued, just like the timer.

After the first block of JavaScript code has been executed, the browser asks itself the question "What is waiting for execution?". In this case, the mouse click handler and the timer are in a pending state. The browser chooses one of them (the click handler) and executes it. The timer will wait for the next available chunk of time in the execution queue.

Note that while the mouse click handler is executing, the first interval-callback is fired. Just like timer-callback, it will be queued. However, be aware that when the interval fires again (while the timer-callback is running), it will be removed from the queue. If all interval-callbacks were to queue up while a large piece of code is executing, this would result in a bunch of functions waiting to be called with no periods of delay between the end of their execution. Instead, browsers tend to wait until there is no function left in the queue before adding another one to the queue.

Thus, we can observe the case when the third firing of the interval-callback coincides with the moment when it is already executing. This illustrates an important feature: intervals do not care about what is currently running, they will be added to the queue without regard to the delay period between executions.

Finally, after the second interval-callback completes, we see that there is nothing left for the JavaScript engine to execute. This means that the browser is again waiting for new asynchronous events. This will happen at the 50ms mark, where the interval-callback will fire again. At that moment, there will be nothing to block it, so it will work immediately.

Let's look at an example that illustrates well the difference between setTimeout and setInterval.
setTimeout(function()( /* Some long block of code... */ setTimeout(arguments.callee, 10); ), 10); setInterval(function()( /* Some long block of code... */ ), 10);
These two options are equivalent at first glance, but in fact they are not. Code using setTimeout will always have a delay of at least 10ms after the previous call (it can be longer, but never less), while code using setInterval will tend to be called every 10ms, regardless of when the previous call ended.

Let's summarize all of the above:
- JavaScript engines use a single-threaded environment, converting asynchronous events into a queue waiting to be executed,
- The setTimeout and setInterval functions are executed fundamentally differently in asynchronous code,
- If the timer cannot be executed at the moment, it will be delayed until the next execution point (which will be longer than the desired delay),
- Intervals (setInterval) can be executed one after another without delay if their execution takes longer than the specified delay.

All this is extremely important information for development. Knowing how the JavaScript engine works, especially with a lot of asynchronous events (which happens a lot), lays a great foundation for building advanced applications.

In programming in scripting languages, from time to time there is a need to create a pause - to suspend the execution of the program for a while, and then continue working. For example, in VBS and PHP scripts, the following methods are possible:

VBS: wscript.sleep 1500 (stop for 1.5 seconds)

PHP: sleep(10); (stop for 10 seconds)

During these pauses, the runtime system (PHP or VBS) doing nothing. A developer trying to intuitively use something similar in Javascript will be unpleasantly surprised. Common Mistake when trying to create a pause in Javascript looks like this:

Function badtest() ( for (var i=1; i< 10; i++) { window.setTimeout("document.getElementById("test1").value += " + i, 900) } }

Do you think that when the queue reaches the drawing of the next digit during the loop, your setTimeout honestly stop Javascript work, wait 0.9 sec., add the required number to the end of the input field and then continue working. But actually it is not: setInterval and setTimeout in Javascript, only the action (or function) specified in parentheses is deferred. In our example, the following will happen:

  1. i = 1;
  2. postpone adding the number "1" to the input field by 0.9 seconds;
  3. immediately after setting this task, the cycle goes further: i=2;
  4. delay adding the number "2" to the input field by 0.9 seconds;

Immediately means, for example, 1 ms (that is, disproportionately small compared to 900 ms): the loop will perform its work almost instantly, creating several pending tasks from the same point in time. This means that all pending "drawing" tasks will be completed at almost the same time, with no pauses between adding new numbers. The cycle starts; everything freezes for 0.9 s; and shirrr - all numbers are shot in a row one after another.

How would you apply it in such a case? setTimeout? It's complicated. You have to call the function recursively(from inside the function the same function), and so that this process is not infinite, set a stop condition (for example, the value of the printed number):

Function welltest() ( if (i< 9) { document.getElementById("test2").value += ++i window.setTimeout("welltest()", 400) } }

And another variable i you have to initialize it outside the function - for example, like this:

Now everything works as it should (we reduced the delay time from 0.9 s to 0.4 s). But for such tasks it is more logical to use not setTimeout a setInterval(although this will require two functions):

Function besttest() ( window.i = 0 window.timer1 = window.setInterval("draw()", 400) ) function draw() ( document.getElementById("test3").value += ++i if (i >= 9) clearInterval(window.timer1) )

Feature of Javascirpt method setInterval in that it does not go away “by itself”, it must be stopped by a special method clearInterval. And to make it clear what exactly to stop, a special identifier is assigned to the task for the deferred action - a timer: window.timer1 = window.setInterval(...) .

Identifiers can also be assigned to tasks, generated method setTimeout. All timer IDs must be different from each other (be unique within the current browser window). Then you can create several different tasks in the window that use pending actions, and these tasks will be executed in parallel (like at the same time, if the computer has enough resources), which is basically impossible in PHP or VBS.

Here is an example page with multiple Javascript timers running at the same time: setinterval.htm (Javascript functions in setinterval.js). All page timers (except menus) can be stopped with the Esc key. All example timers rely on "natural" (rather than abstract) i++) counting - time or distance. All "clocks" are specially out of sync (for clarity). Distance-dependent timers are used in the "indicator" and in the drop-down ("driving") menu.

Drop-down menu

Our pull-out menu is really pull-out (from under the “header”): gaps are left between the elements to see how it slides out. Unexpectedly, it turned out that we cannot make equally smooth exit for lists of different lengths - probably due to low computer performance (AMD Athlon 999 MHz).

It is quite obvious that for beauty and harmony it is necessary that the lists of different menu items fall out at the same time. That is, longer lists should drop out with more high speed, shorter ones - at a lower speed. It would seem that this can be done like this:

  1. We set the total “departure” time, for example, to 200 ms.
  2. If the dropdown list is 20px high, obviously we can move it down one pixel per 10ms interval, and then the whole list will pop up in 200ms.
  3. If the dropdown is 40px high, to fit in at the same time we have to move it down one pixel every 5ms.

By this logic, if the dropdown has a height of 200px, we should move it down one pixel per 1ms. But such a speed does not work on our computer - the browser simply does not have time to draw a new position of the list in one millisecond. Yes. Javascript has time to count (what is there to count?), But the browser (Firefox) does not have time to display. A typical web situation.

Therefore, it is possible to more or less equalize the menu departure time only with the help of crutches, and it is still unclear how this will work for more fast computer. But we must count on the slowest one, right? The algorithm (without taking into account the speed of the computer) turns out to be something like this:

  1. Set the total time to leave the list: time = 224 (ms).
  2. Set the minimum time for one interval in the cycle: delay = 3 (ms).
  3. Set the minimum step for the movement of the list: offset = 1 (px).
  4. We change all this depending on the height of the list: 1) increase the delay (interval) time inversely proportional to the height and directly proportional to the total time time (at a height of 224, the coefficient is 1); 2) if the height is more than 40 px, increase the minimum step in proportion to the height. The constant "40" was obtained empirically for the slowest computer. Tests on a Pentium 4 CPU 2.53GHz computer revealed exactly the same number - 40. Otherwise, the timers run wild, the lists go out of step.

Now the lists are more or less leaving. More or less the same amount of time. On the setinterval.htm page.

Here's Bruce:

Function slide_do(obj, maxtop, offset) ( if (getTopLeft(obj).top< maxtop) { obj.style.top = getTopLeft(obj).top + offset } else { if (obj && obj.timer1) { clearInterval(obj.timer1) obj.timer1 = null } } }

The function itself, which pushes nested lists from the menu, as we see, is very simple. It remains only to run it with something like this line:

ts.timer1 = setInterval(function()(slide_do(ts, maxtop, offset)), delay)

Well, before running, just calculate all these maxtop and offset, and also put the list in the mintop position. What does the "preliminary" function do? slide() 40 lines in size. And all together - in the file setinterval.js . Yes, and this crap won't fucking work without a stylesheet included.

JavaScript timeout is a native javascript function that executes a piece of code after a set time delay (in milliseconds). This can come in handy when you want to display a popup after the user has spent some time on your page. Or you want the effect when you hover over the element to run only after some time. This way, you can avoid unintentionally triggering the effect if the user hovered over by accident.

A simple setTimeout example

To demonstrate how this function works, let's take a look at the following demo, in which a popup appears two seconds after the button is clicked.

View demo

Syntax

The MDN documentation gives the following syntax for setTimeout :

var timeoutID = window.setTimeout(func, ); var timeoutID = window.setTimeout(code, );

  • timeoutID is a numeric id that can be used in conjunction with clearTimeout() to disable the timer;
  • func is the function to be executed;
  • code( in alternative syntax) is the line of code to be executed;
  • delay – duration of the delay in milliseconds after which the function will be launched. The default value is 0.

setTimeout vs window.setTimeout

The above syntax uses window.setTimeout . Why?

In fact, setTimeout and window.setTimeout are pretty much the same function. The only difference is that in the second expression, we use the setTimeout method as a property of the global window object.

Personally, I think that this only greatly complicates the code. If we were to define an alternative JavaScript method timeout that can be found and returned in priority order would run into even more problems.

AT this manual I don't want to mess with the window object, but in general it's up to you which syntax to use.

Examples of using

This could be a function name:

function explode()( alert("Boom!"); ) setTimeout(explode, 2000);

A variable that refers to a function:

var explode = function()( alert("Boom!"); ); setTimeout(explode, 2000);

Or an anonymous function:

setTimeout(function()( alert("Boom!"); ), 2000);

  • Such code is poorly perceived, and, therefore, it will be difficult to modernize or debug it;
  • It involves the use of the eval() method, which can be a potential vulnerability;
  • This method is slower than the others because it needs to run JavaScript interpreter.

Also note that we are using the JavaScript timeout alert method to test the code.

Passing parameters to setTimout

In the first ( Also, cross-browser) option, we pass parameters to the callback function executed with setTimeout .

In the following example, we extract a random greeting from the greetings array and pass it as a parameter to the greet() function, which is executed by setTimeout with a delay of 1 second:

function greet(greeting)( console.log(greeting); ) function getRandom(arr)( return arr; ) var greetings = ["Hello", "Bonjour", "Guten Tag"], randomGreeting = getRandom(greetings); setTimeout(function()( greet(randomGreeting); ), 1000);

View demo

Alternative method

In the syntax at the beginning of this article, there is another method that can be used to pass parameters to the callback function executed by the JavaScript timeout . This method implies the output of all parameters following the delay.

Based on the previous example, we get:

setTimeout(greet, 1000, randomGreeting);

This method will not work in IE 9 and below, where passed parameters are treated as undefined . But in order to solve this problem, MDN has a special polyfill.

Associated issues and “this”

Code executed by setTimeout runs separately from the function that called it. Because of this, we are faced with certain problems, as a solution to which we can use keyword this.

var person = ( firstName: "Jim", introduce: function()( console.log("Hi, I"m " + this.firstName); ) ); person.introduce(); // Outputs: Hi, I" m Jim setTimeout(person.introduce, 50); // Outputs: Hi, I"m undefined

The reason for this output is that in the first example, this points to the person object, while in the second example it points to the global window object, which does not have a firstName property.

To get rid of this inconsistency, you can use several methods:

Force the value of this

This can be done with bind(), a method that creates new feature, which, when called, uses the specified value as the value of the this key. In our case, the specified person object. This gives us as a result:

setTimeout(person.introduce.bind(person), 50);

Note: The bind method was introduced in ECMAScript 5, which means that it will only work in modern browsers. In others, you will get a runtime error when applying it. JavaScript "function timeout error".

Use Library

Many libraries include built-in functions needed to solve the this problem. For example, the jQuery.proxy() method. It takes a function and returns a new one that will always use a certain context. In our case, the context will be:

setTimeout($.proxy(person.introduce, person), 50);

View demo

Turn off the timer

The return value of setTimeout is a numeric id that can be used to disable the timer using the clearTimeout() function:

var timer = setTimeout(myFunction, 3000); clearTimeout(timer);

Let's see it in action. In the following example, if you click on the " start countdown”, the countdown will begin. After it is over, the kittens will get theirs. But if you press the button Stop count down”, the JavaScript timeout will be stopped and reset.

View example

Summing up

setTimeout is an asynchronous function, which means that the received call to this function gets into the queue, and will be executed only after all other actions on the stack have completed. It cannot run concurrently with other functions or on a separate thread.


2022
maccase.ru - Android. Brands. Iron. News