The global setTimeout()
method sets a timer which executes a function or specified piece of code once the timer expires.
The global setTimeout()
method sets a timer which executes a function or specified piece of code once the timer expires.
js
setTimeout(code) setTimeout(code, delay) setTimeout(functionRef) setTimeout(functionRef, delay) setTimeout(functionRef, delay, param1) setTimeout(functionRef, delay, param1, param2) setTimeout(functionRef, delay, param1, param2, /* …, */ paramN)
functionRef
A function
to be executed after the timer expires.
code
An alternative syntax that allows you to include a string instead of a function, which is compiled and executed when the timer expires. This syntax is not recommended for the same reasons that make using eval()
a security risk.
delay
Optional
The time, in milliseconds that the timer should wait before the specified function or code is executed. If this parameter is omitted, a value of 0 is used, meaning execute "immediately", or more accurately, the next event cycle.
Note that in either case, the actual delay may be longer than intended; see Reasons for delays longer than specified below.
Also note that if the value isn't a number, implicit type coercion is silently done on the value to convert it to a number — which can lead to unexpected and surprising results; see Non-number delay values are silently coerced into numbers for an example.
param1
, …, paramN
Optional
Additional arguments which are passed through to the function specified by functionRef
.
The returned timeoutID
is a positive integer value which identifies the timer created by the call to setTimeout()
. This value can be passed to clearTimeout()
to cancel the timeout.
It is guaranteed that a timeoutID
value will never be reused by a subsequent call to setTimeout()
or setInterval()
on the same object (a window or a worker). However, different objects use separate pools of IDs.
Timeouts are cancelled using clearTimeout()
.
To call a function repeatedly (e.g., every N milliseconds), consider using setInterval()
.
If setTimeout()
is called with delay value that's not a number, implicit type coercion is silently done on the value to convert it to a number. For example, the following code incorrectly uses the string "1000"
for the delay value, rather than the number 1000
– but it nevertheless works, because when the code runs, the string is coerced into the number 1000
, and so the code executes 1 second later.
js
setTimeout(() => { console.log("Delayed for 1 second."); }, "1000");
But in many cases, the implicit type coercion can lead to unexpected and surprising results. For example, when the following code runs, the string "1 second"
ultimately gets coerced into the number 0
— and so, the code executes immediately, with zero delay.
js
setTimeout(() => { console.log("Delayed for 1 second."); }, "1 second");
Therefore, don't use strings for the delay value but instead always use numbers:
js
setTimeout(() => { console.log("Delayed for 1 second."); }, 1000);
setTimeout()
is an asynchronous function, meaning that the timer function will not pause execution of other functions in the functions stack. In other words, you cannot use setTimeout()
to create a "pause" before the next function in the function stack fires.
See the following example:
js
setTimeout(() => { console.log("this is the first message"); }, 5000); setTimeout(() => { console.log("this is the second message"); }, 3000); setTimeout(() => { console.log("this is the third message"); }, 1000); // Output: // this is the third message // this is the second message // this is the first message
Notice that the first function does not create a 5-second "pause" before calling the second function. Instead, the first function is called, but waits 5 seconds to execute. While the first function is waiting to execute, the second function is called, and a 3-second wait is applied to the second function before it executes. Since neither the first nor the second function's timers have completed, the third function is called and completes its execution first. Then the second follows. Then finally the first function is executed after its timer finally completes.
To create a progression in which one function only fires after the completion of another function, see the documentation on Promises.
When you pass a method to setTimeout()
, it will be invoked with a this
value that may differ from your expectation. The general issue is explained in detail in the JavaScript reference.
Code executed by setTimeout()
is called from an execution context separate from the function from which setTimeout
was called. The usual rules for setting the this
keyword for the called function apply, and if you have not set this
in the call or with bind
, it will default to the window
(or global
) object. It will not be the same as the this
value for the function that called setTimeout
.
See the following example:
js
const myArray = ["zero", "one", "two"]; myArray.myMethod = function (sProperty) { console.log(arguments.length > 0 ? this[sProperty] : this); }; myArray.myMethod(); // prints "zero,one,two" myArray.myMethod(1); // prints "one"
The above works because when myMethod
is called, its this
is set to myArray
by the call, so within the function, this[sProperty]
is equivalent to myArray[sProperty]
. However, in the following:
js
setTimeout(myArray.myMethod, 1.0 * 1000); // prints "[object Window]" after 1 second setTimeout(myArray.myMethod, 1.5 * 1000, "1"); // prints "undefined" after 1.5 seconds
The myArray.myMethod
function is passed to setTimeout
, then when it's called, its this
is not set, so it defaults to the window
object.
There's also no option to pass a thisArg
to setTimeout
as there is in Array methods such as forEach()
and reduce()
. As shown below, using call
to set this
doesn't work either.
js
setTimeout.call(myArray, myArray.myMethod, 2.0 * 1000); // error setTimeout.call(myArray, myArray.myMethod, 2.5 * 1000, 2); // same error
A common way to solve the problem is to use a wrapper function that sets this
to the required value:
js
setTimeout(function () { myArray.myMethod(); }, 2.0 * 1000); // prints "zero,one,two" after 2 seconds setTimeout(function () { myArray.myMethod("1"); }, 2.5 * 1000); // prints "one" after 2.5 seconds
The wrapper function can be an arrow function:
js
setTimeout(() => { myArray.myMethod(); }, 2.0 * 1000); // prints "zero,one,two" after 2 seconds setTimeout(() => { myArray.myMethod("1"); }, 2.5 * 1000); // prints "one" after 2.5 seconds
Alternatively, you can use bind()
to set the value of this
for all calls to a given function:
js
const myArray = ["zero", "one", "two"]; const myBoundMethod = function (sProperty) { console.log(arguments.length > 0 ? this[sProperty] : this); }.bind(myArray); myBoundMethod(); // prints "zero,one,two" because 'this' is bound to myArray in the function myBoundMethod(1); // prints "one" setTimeout(myBoundMethod, 1.0 * 1000); // still prints "zero,one,two" after 1 second because of the binding setTimeout(myBoundMethod, 1.5 * 1000, "1"); // prints "one" after 1.5 seconds
Passing a string instead of a function to setTimeout()
has the same problems as using eval()
.
js
// Don't do this setTimeout("console.log('Hello World!');", 500);
js
// Do this instead setTimeout(() => { console.log("Hello World!"); }, 500);
A string passed to setTimeout()
is evaluated in the global context, so local symbols in the context where setTimeout()
was called will not be available when the string is evaluated as code.
There are a number of reasons why a timeout may take longer to fire than anticipated. This section describes the most common reasons.
As specified in the HTML standard, browsers will enforce a minimum timeout of 4 milliseconds once a nested call to setTimeout
has been scheduled 5 times.
This can be seen in the following example, in which we nest a call to setTimeout
with a delay of 0
milliseconds, and log the delay each time the handler is called. The first four times, the delay is approximately 0 milliseconds, and after that it is approximately 4 milliseconds:
html
<button id="run">Run</button> <table> <thead> <tr> <th>Previous</th> <th>This</th> <th>Actual delay</th> </tr> </thead> <tbody id="log"></tbody> </table>
js
let last = 0; let iterations = 10; function timeout() { // log the time of this call logline(new Date().getMilliseconds()); // if we are not finished, schedule the next call if (iterations-- > 0) { setTimeout(timeout, 0); } } function run() { // clear the log const log = document.querySelector("#log"); while (log.lastElementChild) { log.removeChild(log.lastElementChild); } // initialize iteration count and the starting timestamp iterations = 10; last = new Date().getMilliseconds(); // start timer setTimeout(timeout, 0); } function logline(now) { // log the last timestamp, the new timestamp, and the difference const tableBody = document.getElementById("log"); const logRow = tableBody.insertRow(); logRow.insertCell().textContent = last; logRow.insertCell().textContent = now; logRow.insertCell().textContent = now - last; last = now; } document.querySelector("#run").addEventListener("click", run);
To reduce the load (and associated battery usage) from background tabs, browsers will enforce a minimum timeout delay in inactive tabs. It may also be waived if a page is playing sound using a Web Audio API AudioContext
.
The specifics of this are browser-dependent:
AudioContext
.Firefox enforces additional throttling for scripts that it recognizes as tracking scripts. When running in the foreground, the throttling minimum delay is still 4ms. In background tabs, however, the throttling minimum delay is 10,000 ms, or 10 seconds, which comes into effect 30 seconds after a document has first loaded.
See Tracking Protection for more details.
The timeout can also fire later than expected if the page (or the OS/browser) is busy with other tasks. One important case to note is that the function or code snippet cannot be executed until the thread that called setTimeout()
has terminated. For example:
js
function foo() { console.log("foo has been called"); } setTimeout(foo, 0); console.log("After setTimeout");
Will write to the console:
After setTimeout foo has been called
This is because even though setTimeout
was called with a delay of zero, it's placed on a queue and scheduled to run at the next opportunity; not immediately. Currently-executing code must complete before functions on the queue are executed, thus the resulting execution order may not be as expected.
Firefox will defer firing setTimeout()
timers while the current tab is loading. Firing is deferred until the main thread is deemed idle (similar to window.requestIdleCallback()), or until the load event is fired.
In WebExtensions, setTimeout()
does not work reliably. Extension authors should use the alarms
API instead.
Browsers store the delay as a 32-bit signed integer internally. This causes an integer overflow when using delays larger than 2,147,483,647 ms (about 24.8 days), resulting in the timeout being executed immediately.
The following example sets up two simple buttons in a web page and hooks them to the setTimeout()
and clearTimeout()
routines. Pressing the first button will set a timeout which shows a message after two seconds and stores the timeout id for use by clearTimeout()
. You may optionally cancel this timeout by pressing on the second button.
html
<button onclick="delayedMessage();">Show a message after two seconds</button> <button onclick="clearMessage();">Cancel message before it happens</button> <div id="output"></div>
js
let timeoutID; function setOutput(outputContent) { document.querySelector("#output").textContent = outputContent; } function delayedMessage() { setOutput(""); timeoutID = setTimeout(setOutput, 2 * 1000, "That was really slow!"); } function clearMessage() { clearTimeout(timeoutID); }
See also the clearTimeout()
example.
Specification |
---|
HTML Standard # dom-settimeout-dev |
Desktop | Mobile | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
Chrome | Edge | Firefox | Internet Explorer | Opera | Safari | WebView Android | Chrome Android | Firefox for Android | Opera Android | Safari on IOS | Samsung Internet | |
setTimeout |
1 | 12 | 1 | 4 | 4 | 1 | 4.4 | 18 | 4 | 10.1 | 1 | 1.0 |
supports_parameters_for_callback |
1 | 12 | 1 | 10 | ≤15 | 1.2 | ≤37 | 18 | 4 | ≤14 | 1 | 1.0 |
worker_support |
3 | 12 | 3.5 | 10 | ≤12.1 | 4 | 4.4 | 18 | 4 | ≤12.1 | 5 | 1.0 |
© 2005–2023 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/setTimeout