Setting up hardware and software

Javascript prevent multiple setinterval timers from running at the same time. How JavaScript timers work

Source: http://learn.javascript.ru/settimeout-setinterval

Almost all JavaScript implementations have an internal timer scheduler that allows you to schedule a function to be called after a specified period of time.

In particular, this feature is supported in browsers and in the Node.JS server.

setTimeout

Syntax:

var timerId = setTimeout(func/code, delay[, arg1, arg2...])

Options:

  • func/code
    • A function or line of code to be executed.
    • The string is maintained for compatibility purposes and is not recommended.
  • delay
    • Latency in milliseconds, 1000 milliseconds equals 1 second.
  • arg1, arg2…
    • Arguments to pass to the function. Not supported in IE9-.
    • The function will be executed after the time specified in the delay parameter.

For example, the following code will trigger alert("Hello") after one second:

function func () ( alert("Hello" ); ) setTimeout(func, 1000 );

If the first argument is a string, then the interpreter creates an anonymous function from that string.

That is, this entry works exactly the same:

SetTimeout("alert("Hello")" , 1000 );

Use anonymous functions instead:

SetTimeout(function () ( alert("Hello" ) ), 1000 );

Parameters for function and context

In all modern browsers Given IE10, setTimeout allows you to specify function parameters.

The example below will output "Hello, I'm Vasya" everywhere except IE9-:

function sayHi (who) ( alert("Hello, I'm " + who); ) setTimeout(sayHi, 1000 , "Vasya" );

...However, in most cases we need support from the old IE, and it does not allow you to specify arguments. Therefore, in order to transfer them, they wrap the call in an anonymous function:

function sayHi (who) ( alert("Hi, I'm " + who); ) setTimeout(function () ( sayHi("Vasya") ), 1000 );

Calling setTimeout does not pass the this context.

In particular, calling an object method via setTimeout will work in the global context. This may lead to incorrect results.

For example, let's call user.sayHi() after one second:

function User (id) function () ( alert(this .id); ); ) var user = new User(12345); setTimeout(user.sayHi, 1000 ); // expected 12345, but will output "undefined"

Since setTimeout will run the user.sayHi function in the global context, it will not have access to the object via this .

In other words, these two calls to setTimeout do the same thing:

// (1) one line setTimeout(user.sayHi, 1000 ); // (2) the same thing in two lines var func = user.sayHi; setTimeout(func, 1000 );

Fortunately, this problem is also easily solved by creating an intermediate function:

function User (id) ( this .id = id; this .sayHi = function () ( alert(this .id); ); ) var user = new User(12345); setTimeout(function () ( user.sayHi(); ), 1000 );

A wrapper function is used to pass arguments cross-browser and preserve execution context.

Cancellation of execution

The setTimeout function returns a timerId that can be used to cancel the action.

Syntax:

ClearTimeout(timerId)

In the following example we set a timeout and then delete (changed our mind). As a result, nothing happens.

var timerId = setTimeout(function () ( alert(1) ), 1000 ); clearTimeout(timerId); setInterval

The setInterval method has a syntax similar to setTimeout.

var timerId = setInterval(func/code, delay[, arg1, arg2...])

The meaning of the arguments is the same. But, unlike setTimeout , it does not run the function once, but repeats it regularly at a specified time interval. You can stop execution by calling:

ClearInterval(timerId)

The following example, when run, will display a message every two seconds until you click on the “Stop” button:

var i = 1 ;

var timer = setInterval(function () ( alert(i++) ), 2000 );

Queuing and overlaying calls in setInterval

The call setInterval(function, delay) causes the function to execute at the specified time interval. But there is a subtlety here.

In fact, the pause between calls is less than the specified interval.

For example, let's take setInterval(function() ( func(i++) ), 100) . It executes func every 100ms, incrementing the counter each time.

In the picture below, the red block is the execution time of func . Interblock time is the time between function runs and is less than the set delay!

That is, the browser initiates the launch of the function neatly every 100ms, without taking into account the execution time of the function itself.

The image below illustrates what happens for a function that takes a long time to execute.

The function call initiated by setInterval is added to the queue and occurs immediately when possible:

The second launch of the function occurs immediately after the end of the first:

Execution is not queued more than once.

If a function takes longer to execute than several scheduled executions, it will still queue once. So there is no “accumulation” of launches.

In the image below, setInterval tries to execute the function in 200ms and queues the call. At 300ms and 400ms the timer wakes up again, but nothing happens.

Calling setInterval(function, delay) does not guarantee actual delay between executions.

There are cases when the actual delay is greater or less than the specified one. In general, it is not a fact that there will be at least some delay.

Repeating nested setTimeout

In cases where not just regular repetition is needed, but a delay between runs is required, setTimeout is used to re-set each time the function is executed.

Below is an example that issues an alert with 2 second intervals between them.

var i = 1 ;

var timer = setTimeout(function run () ( alert(i++); timer = setTimeout(run, 2000 ); ), 2000 );

The execution timeline will have fixed delays between runs. Illustration for 100ms delay:

Minimum timer delay

The browser timer has the lowest possible latency. It varies from approximately zero to 4ms in modern browsers. In older ones it can be longer and reach 15ms.

According to the standard, the minimum delay is 4ms. So there is no difference between setTimeout(..,1) and setTimeout(..,4) .

  • The zero-latency behavior of setTimeout and setInterval is browser-specific.
  • In Opera, setTimeout(.., 0) is the same as setTimeout(.., 4) . It is executed less frequently than setTimeout(.. ,2). This is a feature of this browser. IN Internet Explorer
  • , zero delay setInterval(.., 0) will not work. This applies specifically to setInterval , i.e. setTimeout(.., 0) works fine.

    Actual trigger frequency

    Most browsers (desktop ones primarily) continue to execute setTimeout / setInterval even if the tab is inactive. At the same time, a number of them (Chrome, FF, IE10) reduce the minimum timer frequency to 1 time per second. It turns out that the timer will work in the “background” tab, but rarely.

    When running on battery power, on a laptop, browsers can also reduce the frequency to execute code less often and save battery power. IE is especially famous for this. The reduction can reach several times, depending on the settings. If the CPU load is too high, JavaScript may not be able to process timers in a timely manner. This will skip some setInterval runs.

    Conclusion: a frequency of 4ms is worth focusing on, but you shouldn’t count on it.

    Outputting intervals to the console The code that counts the time intervals between calls looks something like this:

    var timeMark = new Date; setTimeout(function go () ( var diff = new Date - timeMark; // print the next delay to the console instead of the page console .log(diff); // remember the time at the very end, // to measure the delay between calls timeMark = new Date ; setTimeout(go, 100 ), 100 ); The trick is setTimeout(func, 0)

    This trick is worthy of entering the annals of JavaScript hacks.

    The function is wrapped in setTimeout(func, 0) if you want to run it after the end of the current script.

    The thing is that setTimeout never executes the function right away. He only plans its implementation. But the JavaScript interpreter will begin to perform the planned functions only after the current script is executed.

    According to the standard, setTimeout cannot execute a function with a delay of 0 anyway. As we said earlier, the delay will usually be 4ms. But the main thing here is that execution in any case will take place after the execution of the current code.

    For example:

    var result; function showResult () ( alert(result); ) setTimeout(showResult, 0 ); result = 2 *2 ; // will output 4 Total

    The setInterval(func, delay) and setTimeout(func, delay) methods allow you to run func regularly/once every delay milliseconds.

    Both methods return the timer ID. It is used to stop execution by calling clearInterval / clearTimeout .

    | | setInterval | setTimeout | || ----------- | ---------- | | Timing | The call is strictly on a timer. If the interpreter is busy, one call is queued. Function execution time is not taken into account, so the time interval from the end of one run to the start of another may vary. | A recursive call to setTimeout is used instead of setInterval where a fixed pause between executions is needed. | | Delay | Minimum delay: 4ms. | Minimum delay: 4ms. | | Browser Features | Latency 0 does not work in IE. | In Opera, zero latency is equivalent to 4ms, and other delays are handled accurately, including non-standard 1ms, 2ms and 3ms. |

    The setInterval() method, offered on the Window and Worker interfaces, repeatedly calls a function or executes a code snippet, with a fixed time delay between each call. The clearInterval() method of the WindowOrWorkerGlobalScope mixin cancels a timed, repeating action which was previously established by a call to setInterval(). clearInterval() The WindowOrWorkerGlobalScope mixin describes several features common to the Window and WorkerGlobalScope interfaces. WindowOrWorkerGlobalScope

    mixin. Syntax = var intervalID scope .setInterval(, delay, [func, arg1, ...]); Syntax = var intervalID scope arg2, delay code The Function constructor creates a new Function object. Calling the constructor directly can create functions dynamically, but suffers from security and similar (but far less significant) performance issues to eval. However, unlike eval, the Function constructor creates functions which execute in the global scope only. function to be executed every delay milliseconds. The function is not passed any arguments, and no return value is expected. code An optional syntax allows you to include a string instead of a function, which is compiled and executed every delay milliseconds. This syntax is for the same reasons that make using a security risk. .setInterval( delay The time, in milliseconds (thousandths of a second), the timer should delay in between executions of the specified function or code. See below for details on the permitted range of delay values.

    arg1, ..., argN Optional Additional arguments which are passed through to the function specified by once the timer expires. Note : Passing additional arguments to setInterval() in the first syntax

    does not

    work in Internet Explorer 9 and earlier. If you want to enable this functionality on that browser, you must use a polyfill (see the section).

    Return value It may be helpful to be aware that setInterval() and The setTimeout() method of the WindowOrWorkerGlobalScope mixin (and successor to Window.setTimeout()) sets a timer which executes a function or specified piece of code once the timer expires. share the same pool of IDs, and that clearInterval() and The clearTimeout() method of the WindowOrWorkerGlobalScope mixin cancels a timeout previously established by calling setTimeout().

    clearTimeout()

    can technically be used interchangeably. For clarity, however, you should try to always match them to avoid confusion when maintaining your code.

    Note: The delay argument is converted to a signed 32-bit integer. This effectively limits delay to 2147483647 ms, since it"s specified as a signed integer in the IDL.

    Examples Example 1: Basic syntax

    The following example demonstrates setInterval() "s basic syntax.

    Var intervalID = window.setInterval(myCallback, 500, "Parameter 1", "Parameter 2"); function myCallback(a, b) ( // Your code here // Parameters are purely optional. console.log(a); console.log(b); )

    Example 2: Alternating two colors

    The following example calls the flashtext() function once a second until the Stop button is pressed.

    setInterval/clearInterval example var nIntervId;

    function changeColor() ( nIntervId = setInterval(flashText, 1000); ) function flashText() ( var oElem = document.getElementById("my_box"); oElem.style.color = oElem.style.color == "red" ? " blue" : "red"; // oElem.style.color == "red" ? "blue" : "red" is a ternary operator. ) function stopTextColor() ( clearInterval(nIntervId); )

    The following example simulates typewriter by first clearing and then slowly typing content into the NodeList that matches a specified group of selectors.

    JavaScript Typewriter - MDN Example function Typewriter (sSelector, nRate) ( function clean () ( clearInterval(nIntervId); bTyping = false; bStart = true; oCurrent = null; aSheets.length = nIdx = 0; ) function scroll (oSheet, nPos , bEraseAndStop) ( if (!oSheet.hasOwnProperty("parts") || aMap.length< nPos) { return true; } var oRel, bExit = false; if (aMap.length === nPos) { aMap.push(0); } while (aMap < oSheet.parts.length) { oRel = oSheet.parts]; scroll(oRel, nPos + 1, bEraseAndStop) ? aMap++ : bExit = true; if (bEraseAndStop && (oRel.ref.nodeType - 1 | 1) === 3 && oRel.ref.nodeValue) { bExit = true; oCurrent = oRel.ref; sPart = oCurrent.nodeValue; oCurrent.nodeValue = ""; } oSheet.ref.appendChild(oRel.ref); if (bExit) { return false; } } aMap.length--; return true; } function typewrite () { if (sPart.length === 0 && scroll(aSheets, 0, true) && nIdx++ === aSheets.length - 1) { clean(); return; } oCurrent.nodeValue += sPart.charAt(0); sPart = sPart.slice(1); } function Sheet (oNode) { this.ref = oNode; if (!oNode.hasChildNodes()) { return; } this.parts = Array.prototype.slice.call(oNode.childNodes); for (var nChild = 0; nChild < this.parts.length; nChild++) { oNode.removeChild(this.parts); this.parts = new Sheet(this.parts); } } var nIntervId, oCurrent = null, bTyping = false, bStart = true, nIdx = 0, sPart = "", aSheets = , aMap = ; this.rate = nRate || 100; this.play = function () { if (bTyping) { return; } if (bStart) { var aItems = document.querySelectorAll(sSelector); if (aItems.length === 0) { return; } for (var nItem = 0; nItem < aItems.length; nItem++) { aSheets.push(new Sheet(aItems)); /* Uncomment the following line if you have previously hidden your elements via CSS: */ // aItems.style.visibility = "visible"; } bStart = false; } nIntervId = setInterval(typewrite, this.rate); bTyping = true; }; this.pause = function () { clearInterval(nIntervId); bTyping = false; }; this.terminate = function () { oCurrent.nodeValue += sPart; sPart = ""; for (nIdx; nIdx < aSheets.length; scroll(aSheets, 0, false)); clean(); }; } /* usage: */ var oTWExample1 = new Typewriter(/* elements: */ "#article, h1, #info, #copyleft", /* frame rate (optional): */ 15); /* default frame rate is 100: */ var oTWExample2 = new Typewriter("#controls"); /* you can also change the frame rate value modifying the "rate" property; for example: */ // oTWExample2.rate = 150; onload = function () { oTWExample1.play(); oTWExample2.play(); }; span.intLink, a, a:visited { cursor: pointer; color: #000000; text-decoration: underline; } #info { width: 180px; height: 150px; float: right; background-color: #eeeeff; padding: 4px; overflow: auto; font-size: 12px; margin: 4px; border-radius: 5px; /* visibility: hidden; */ }

    CopyLeft 2012 by Mozilla Developer Network

    [ Play | Pause | Terminate]

    Vivamus blandit massa ut metus mattis in fringilla lectus imperdiet. Proin ac ante a felis ornare vehicula. Fusce pellentesque lacus vitae eros convallis ut mollis magna pellentesque. Pellentesque placerat enim at lacus ultricies vitae facilisis nisi fringilla. In tincidunt tincidunt tincidunt.

    JavaScript Typewriter

    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam ultrices dolor ac dolor imperdiet ullamcorper. Suspendisse quam libero, luctus auctor mollis sed, malesuada condimentum magna. Quisque in ante tellus, in placerat est. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec a mi magna, quis mattis dolor. Etiam sit amet ligula quis urna auctor imperdiet nec faucibus ante. Mauris vel consectetur dolor. Nunc eget elit eget velit pulvinar fringilla consectetur aliquam purus. Curabitur convallis, justo posuere porta egestas, velit erat ornare tortor, non viverra justo diam eget arcu. Phasellus adipiscing fermentum nibh ac commodo. Nam turpis nunc, suscipit a hendrerit vitae, volutpat non ipsum.
    Phasellus ac nisl lorem:

    Duis lobortis sapien quis nisl luctus porttitor. In tempor semper libero, eu tincidunt dolor eleifend sit amet. Ut nec velit in dolor tincidunt rhoncus non non diam. Morbi auctor ornare orci, non euismod felis gravida nec. Curabitur elementum nisi a eros rutrum nec blandit diam placerat. Aenean tincidunt risus ut nisi consectetur cursus. Ut vitae quam elit. Donec dignissim est in quam tempor consequat. Aliquam aliquam diam non felis convallis suscipit. Nulla facilisi. Donec lacus risus, dignissim et fringilla et, egestas vel eros. Duis malesuada accumsan dui, at fringilla mauris bibStartum quis. Cras adipiscing ultricies fermentum. Praesent bibStartum condimentum feugiat.

    Nam faucibus, ligula eu fringilla pulvinar, lectus tellus iaculis nunc, vitae scelerisque metus leo non metus. Proin mattis lobortis lobortis. Quisque accumsan faucibus erat, vel varius tortor ultricies ac. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nec libero nunc. Nullam tortor nunc, elementum a consectetur et, ultrices eu orci. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque a nisl eu sem vehicula egestas.

    Callback arguments

    As previously discussed, Internet Explorer versions 9 and below do not support the passing of arguments to the callback function in either setTimeout() or setInterval() . The following IE-specific code demonstrates a method for overcoming this limitation. To use, simply add the following code to the top of your script.

    /*\ |*| |*| IE-specific polyfill that enables the passage of arbitrary arguments to the |*| callback functions of javascript timers (HTML5 standard syntax)..setInterval |*| https://site/User:fusionchess |*| |*| Syntax: |*| var timeoutID = window.setTimeout(func, delay[, arg1, arg2, ...]); |*| var timeoutID = window.setTimeout(code, delay); |*| var intervalID = window.setInterval(func, delay[, arg1, arg2, ...]); |*| var intervalID = window.setInterval(code, delay); |*| \*/ if (document.all && !window.setTimeout.isPolyfill) ( var __nativeST__ = window.setTimeout; window.setTimeout = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) ( var aArgs = Array .prototype.slice.call(arguments, 2); return __nativeST__(vCallback instanceof Function () ( vCallback.apply(null, aArgs); ) : vCallback, nDelay ); if (document.all && !window.setInterval.isPolyfill) ( var __nativeSI__ = window.setInterval; window.setInterval = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) ( var aArgs = Array.prototype. slice.call(arguments, 2); return __nativeSI__(vCallback instanceof Function () ( vCallback.apply(null, aArgs); ) : vCallback, nDelay );

    Another possibility is to use an anonymous function to call your callback, although this solution is a bit more expensive. Example:

    Var intervalID = setInterval(function() ( myFunc("one", "two", "three"); ), 1000);

    var intervalID = setInterval(function(arg1) ().bind(undefined, 10), 1000);

    Inactive tabs Requires Gecko 5.0(Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2)

    Starting in Gecko 5.0 (Firefox 5.0 / Thunderbird 5.0 / SeaMonkey 2.2), intervals are clamped to fire no more often than once per second in inactive tabs. The" this

    "problem When you pass a method to setInterval() or any other function, it is invoked with the wrong this value. This problem is explained in detail in the.

    JavaScript reference

    Explanation When you pass a method to setInterval() or any other function, it is invoked with the wrong Code executed by setInterval() runs in a separate execution context than the function from which it was called. As a consequence, the

    MyArray = ["zero", "one", "two"]; myArray.myMethod = function (sProperty) ( alert(arguments.length > 0 ? this : this); ); myArray.myMethod(); // prints "zero,one,two" myArray.myMethod(1); // prints "one" setTimeout(myArray.myMethod, 1000); // prints "" after 1 second setTimeout(myArray.myMethod, 1500, "1"); // prints "undefined" after 1.5 seconds // passing the "this" object with .call won"t work // because this will change the value of this inside setTimeout itself // while we want to change the value of this inside myArray.myMethod // in fact, it will be an error because setTimeout code expects this to be the window object: setTimeout.call(myArray, myArray.myMethod, 2000); // error: "NS_ERROR_XPC_BAD_OP_ON_WN_PROTO: Illegal operation on WrappedNative prototype object" setTimeout.call(myArray, myArray.myMethod, 2500, 2); // same error

    As you can see there are no ways to pass the this object to the callback function in the legacy JavaScript.

    A possible solution

    A possible way to solve the "this" problem is to replace the two native setTimeout() or setInterval() global functions with two non-native those that enable their invocation through the Function.prototype.call method. The following example shows a possible replacement:

    // Enable the passage of the "this" object through the JavaScript timers var __nativeST__ = window.setTimeout, __nativeSI__ = window.setInterval; window.setTimeout = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) ( var oThis = this, aArgs = Array.prototype.slice.call(arguments, 2); return __nativeST__(vCallback instanceof Function ? function () ( vCallback.apply(oThis, aArgs); ) : vCallback, nDelay ); window.setInterval = function (vCallback, nDelay /*, argumentToPass1, argumentToPass2, etc. */) ( var oThis = this, aArgs = Array.prototype.slice.call(arguments, 2); return __nativeSI__(vCallback instanceof Function ? function () ( vCallback.apply(oThis, aArgs); ) : vCallback, nDelay );

    These two replacements also enable the HTML5 standard passage of arbitrary arguments to the callback functions of timers in IE. So they can be used as non-standard-compliant polyfills also. See the for a standard-compliant polyfill.

    New feature test:

    MyArray = ["zero", "one", "two"]; myArray.myMethod = function (sProperty) ( alert(arguments.length > 0 ? this : this); ); setTimeout(alert, 1500, "Hello world!"); // the standard use of setTimeout and setInterval is preserved, but... setTimeout.call(myArray, myArray.myMethod, 2000); // prints "zero,one,two" after 2 seconds setTimeout.call(myArray, myArray.myMethod, 2500, 2); // prints "two" after 2.5 seconds

    For a more complex but still modular version of it ( Daemon) see JavaScript Daemons Management. This more complex version is nothing but a large and scalable collection of methods for the Daemon constructor. However, the Daemon constructor itself is nothing but a clone of MiniDaemon with an added support for init and onstart functions declared during the instantiation of the daemon. So the MiniDaemon framework remains the recommended way for simple animations , because Daemon without its collection of methods is essentially a clone of it.

    minidaemon.js /*\ |*| |*| :: MiniDaemon:: |*| |*| Revision #2 - September 26, 2014.setInterval |*| https://site/User:fusionchess |*| https://github.com/madmurphy/minidaemon.js |*| |*| This framework is released under the GNU Lesser General Public License, version 3 or later. |*| http://www.gnu.org/licenses/lgpl-3.0.html |*| \*/ function MiniDaemon (oOwner, fTask, nRate, nLen) ( if (!(this && this instanceof MiniDaemon)) ( return; ) if (arguments.length< 2) { throw new TypeError("MiniDaemon - not enough arguments"); ) if (oOwner) ( this.owner = oOwner; ) this.task = fTask; if (isFinite(nRate) && nRate > 0) ( this.rate = Math.floor(nRate); ) if (nLen > 0) ( this.length = Math.floor(nLen); ) ) MiniDaemon.prototype.owner = null; MiniDaemon.prototype.task = null; MiniDaemon.prototype.rate = 100; * These properties should be read-only */ MiniDaemon.prototype.SESSION = -1; MiniDaemon.prototype.INDEX = 0; MiniDaemon.prototype.PAUSED = true; MiniDaemon.prototype.BACKW = true; .forceCall = function (oDmn) ( oDmn.INDEX += oDmn.BACKW ? -1: 1; if (oDmn.task.call(oDmn.owner, oDmn.INDEX, oDmn.length, oDmn.BACKW) === false || oDmn.isAtEnd()) ( oDmn.pause(); return false; ) return true ); /* Instances methods */ MiniDaemon.prototype.isAtEnd = function () ( return this.BACKW ? isFinite(this.length ) && this.INDEX< 1: this.INDEX + 1 >this.length; ); MiniDaemon.prototype.synchronize = function () ( if (this.PAUSED) ( return; ) clearInterval(this.SESSION); this.SESSION = setInterval(MiniDaemon.forceCall, this.rate, this); ); MiniDaemon.prototype.pause = function () ( clearInterval(this.SESSION); this.PAUSED = true; ); MiniDaemon.prototype.start = function (bReverse) ( var bBackw = Boolean(bReverse); if (this.BACKW === bBackw && (this.isAtEnd() || !this.PAUSED)) ( return; ) this.BACKW = bBackw; this.PAUSED = false; this.synchronize();

    MiniDaemon passes arguments to the callback function. If you want to work on it with browsers that natively do not support this feature, use one of the methods proposed above.

    Syntax

    var myDaemon = new MiniDaemon( thisObject, callback[ , rate [, length]]);

    Description Usage notes

    The setInterval() function is commonly used to set a delay for functions that are executed again and again, such as animations. You can cancel the interval using WindowOrWorkerGlobalScope.clearInterval().

    If you wish to have your function called once after the specified delay, use .

    Delay restrictions

    It"s possible for intervals to be nested; that is, the callback for setInterval() can in turn call setInterval() to start another interval running, even though the first one is still going. To mitigate the potential impact this can have on performance, once intervals are nested beyond five levels deep, the browser will automatically enforce a 4 ms minimum value for the interval. Attempts to specify a value less than 4 ms in deeply-nested calls to setInterval() will be pinned to 4 ms.

    Browsers may enforce even more stringent minimum values ​​for the interval under some circumstances, although these should not be common. Note also that the actual amount of time that elapses between calls to the callback may be longer than the given delay; see Reasons for delays longer than specified in WindowOrWorkerGlobalScope.setTimeout() for examples.

    Ensure that execution duration is shorter than interval frequency

    If there is a possibility that your logic could take longer to execute than the interval time, it is recommended that you recursively call a named function using It may be helpful to be aware that setInterval() and. For example, if using setInterval() to poll a remote server every 5 seconds, network latency, an unresponsive server, and a host of other issues could prevent the request from completing in its allotted time. As such, you may find yourself with queued up XHR requests that won"t necessarily return in order.

    • From:
    • Registered: 2014.07.08
    • Posts: 3,896
    • Likes: 497
    Topic: SetTimeOut and SetInterval, which is better to use in JavaScript?

    The setInterval function is designed to run code multiple times at regular intervals. However, it has a number of disadvantages, mainly different behavior in different browsers.

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

    var d1 = new Date(), d2 = new Date(); setInterval(function() ( var d = new Date(); document.body.innerHTML += (d - d1) + " " + (d - d2) + "
    "; // Put a mark 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 only difference will be in the spread of values. The smallest difference is 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 that is less noticeable and more difficult to reproduce, but can sometimes cause a lot of trouble, is resistance to system time changes. If you run the following test

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

    And after launch translate system time a minute ago, then in Firefox browsers and Safari, the number change will pause, and after a minute it will start again. Of course, manual translation of system time is an extremely rare situation, but on many systems it is configured automatic synchronization time with servers on the Internet, so in some situations this factor cannot be discounted.

    Another small minus setInterval functions- 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 disadvantages 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.

    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 for new data every 5 seconds. If the server is overloaded, you can increase the polling interval to 10, 20, 60 seconds... And then return it back when everything returns to normal.

    If we regularly run CPU-intensive tasks, then we can estimate the time spent on their execution and plan the next run 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 the 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 100 ms and call func(i):

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

    This is natural, because the operating time of the function is not taken into account in any way; it “eats up” part of the interval.

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

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

    If the function runs longer than the setInterval pause, then 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?

    It all depends on the task at hand. Initially, SetTimeOut is used to start the timer once, and SetInterval is used to start a loop. But both functions can be used to run scripts cyclically, if, for example, you run them recursively in SetTimeOut functions, then it will act almost identically to SetInterval.

    The disadvantage 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 queries, then the interval time will be significantly reduced, and it may differ in different browsers.

    But again, if the function or request is minimized, then the end user is unlikely to feel the difference.
    Therefore, what to use is up to everyone to decide for themselves.

    JavaScript timeout is a native javascript function that executes a piece of code after a specified time delay (in milliseconds). This can be useful when you need to display a popup after the user has spent some time on your page. Or do you want the effect when you hover over an element to start only after some time has passed? This way, you can avoid unintentionally triggering an effect if the user hovered over it accidentally.

    Simple setTimeout example

    To demonstrate how this feature works, I suggest taking a look at the following demo, in which a pop-up window appears two seconds after the button is clicked.

    View demo

    Syntax

    The MDN documentation provides the following syntax for setTimeout:

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

    • timeoutID – a numeric id that can be used in combination with clearTimeout() to disable the timer;
    • func – function to be executed;
    • code (in alternative syntax) – line of code to be executed;
    • delay – the 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 practically 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 this just makes the code much more complicated. If we were to define an alternative JavaScript method timeout , which could be found and returned in priority order, we would run into even more problems.

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

    Examples of using

    This could be the name of the function:

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

    Variable that refers to the function:

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

    Or an anonymous function:

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

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

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

    Passing parameters to setTimout

    In the first (and cross-browser) option, we pass parameters to the callback function, executed using 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 given at the beginning of the article, there is another method by which you can pass parameters to the callback function executed by 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 the passed parameters are treated as undefined . But there is a special polyfill on MDN to solve this problem.

    Related problems and “this”

    The code executed by setTimeout runs separately from the function that called it. Because of this, we are faced with certain problems, the solution to which can be used 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, and 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 this to be set

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

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

    Note: the bind method was introduced in ECMAScript 5, which means it will only work in modern browsers. In others, when you use it you will receive an error JavaScript execution"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 specific context. In our case, the context will be:

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

    View demo

    Disabling 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” button, the countdown will begin. After it is completed, the kittens will get theirs. But if you click the “Stop countdown” button, the JavaScript timeout timer will be stopped and reset.

    View example

    Let's sum it up

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

    Did you like the article? Share with your friends!
    Was this article helpful?
    Yes
    No
    Thanks for your feedback!
    Something went wrong and your vote was not counted.
    Thank you. Your message has been sent
    Found an error in the text?
    Select it, click Ctrl + Enter and we will fix everything!