Living Standard — Last Updated 22 November 2024
The setTimeout()
and setInterval()
methods allow authors to schedule timer-based
callbacks.
id = self.setTimeout(handler [, timeout [, ...arguments ] ])
Support in all current engines.
Schedules a timeout to run handler after timeout milliseconds. Any arguments are passed straight through to the handler.
id = self.setTimeout(code [, timeout ])
Schedules a timeout to compile and run code after timeout milliseconds.
self.clearTimeout(id)
Support in all current engines.
Cancels the timeout set with setTimeout()
or setInterval()
identified by id.
id = self.setInterval(handler [, timeout [, ...arguments ] ])
Support in all current engines.
Schedules a timeout to run handler every timeout milliseconds. Any arguments are passed straight through to the handler.
id = self.setInterval(code [, timeout ])
Schedules a timeout to compile and run code every timeout milliseconds.
self.clearInterval(id)
Support in all current engines.
Cancels the timeout set with setInterval()
or setTimeout()
identified by id.
Timers can be nested; after five such nested timers, however, the interval is forced to be at least four milliseconds.
This API does not guarantee that timers will run exactly on schedule. Delays due to CPU load, other tasks, etc, are to be expected.
Objects that implement the WindowOrWorkerGlobalScope
mixin have a
map of setTimeout and setInterval IDs, which is
an ordered map, initially empty. Each key in this map
is a positive integer, corresponding to the return value of a setTimeout()
or setInterval()
call.
Each value is a unique internal value, corresponding
to a key in the object's map of active timers.
The setTimeout(handler, timeout,
...arguments)
method steps are to return the result of running the
timer initialization steps given this, handler,
timeout, arguments, and false.
The setInterval(handler, timeout,
...arguments)
method steps are to return the result of running the
timer initialization steps given this, handler,
timeout, arguments, and true.
The clearTimeout(id)
and clearInterval(id)
method steps
are to remove this's map of setTimeout and
setInterval IDs[id].
Because clearTimeout()
and clearInterval()
clear entries from the same map, either method
can be used to clear timers created by setTimeout()
or setInterval()
.
To perform the timer initialization
steps, given a WindowOrWorkerGlobalScope
global, a string or Function
or TrustedScript
handler, a number timeout, a list arguments, a boolean
repeat, and optionally (and only if repeat is true) a number
previousId, perform the following steps. They return a number.
Let thisArg be global if that is a WorkerGlobalScope
object; otherwise let thisArg be the WindowProxy
that corresponds to
global.
If previousId was given, let id be previousId; otherwise, let id be an implementation-defined integer that is greater than zero and does not already exist in global's map of setTimeout and setInterval IDs.
If the surrounding agent's event loop's currently running task is a task that was created by this algorithm, then let nesting level be the task's timer nesting level. Otherwise, let nesting level be zero.
The task's timer nesting level is used both for nested calls to
setTimeout()
, and for the repeating timers created by
setInterval()
. (Or, indeed, for any combination of the
two.) In other words, it represents nested invocations of this algorithm, not of a particular
method.
If timeout is less than 0, then set timeout to 0.
If nesting level is greater than 5, and timeout is less than 4, then set timeout to 4.
Let realm be global's relevant realm.
Let initiating script be the active script.
Let uniqueHandle be null.
Let task be a task that runs the following substeps:
Assert: uniqueHandle is a unique internal value, not null.
If id does not exist in global's map of setTimeout and setInterval IDs, then abort these steps.
If global's map of setTimeout and setInterval IDs[id] does not equal uniqueHandle, then abort these steps.
This accommodates for the ID having been cleared by a clearTimeout()
or clearInterval()
call, and being reused by a subsequent
setTimeout()
or setInterval()
call.
Record timing info for timer handler given handler, global's relevant settings object, and repeat.
If handler is a Function
, then invoke handler given
arguments and "report
", and with callback this value set to thisArg.
Otherwise:
If previousId was not given:
Let globalName be "Window
" if global
is a Window
object; "Worker
" otherwise.
Let methodName be "setInterval
" if
repeat is true; "setTimeout
" otherwise.
Let sink be a concatenation of globalName, U+0020 SPACE, and methodName.
Set handler to the result of invoking the Get Trusted Type compliant string algorithm with
TrustedScript
, global,
handler, sink, and "script
".
Assert: handler is a string.
Perform EnsureCSPDoesNotBlockStringCompilation(realm, « », handler, handler, timer, « », handler). If this throws an exception, catch it, report it for global, and abort these steps.
Let settings object be global's relevant settings object.
Let fetch options be the default script fetch options.
Let base URL be settings object's API base URL.
If initiating script is not null, then:
Set fetch options to a script fetch options whose cryptographic nonce is initiating
script's fetch options's
cryptographic nonce, integrity metadata is the empty
string, parser metadata is
"not-parser-inserted
", credentials mode is
initiating script's fetch
options's credentials
mode, referrer
policy is initiating script's fetch options's referrer policy, and fetch priority is "auto
".
Set base URL to initiating script's base URL.
The effect of these steps ensures that the string compilation done by setTimeout()
and setInterval()
behaves equivalently to that done by
eval()
. That is, module script fetches via import()
will behave the same in both contexts.
Let script be the result of creating a classic script given handler, settings object, base URL, and fetch options.
Run the classic script script.
If id does not exist in global's map of setTimeout and setInterval IDs, then abort these steps.
If global's map of setTimeout and setInterval IDs[id] does not equal uniqueHandle, then abort these steps.
The ID might have been removed via the author code in handler
calling clearTimeout()
or clearInterval()
. Checking that uniqueHandle isn't different
accounts for the possibility of the ID, after having been cleared, being reused by a
subsequent setTimeout()
or setInterval()
call.
If repeat is true, then perform the timer initialization steps again, given global, handler, timeout, arguments, true, and id.
Otherwise, remove global's map of setTimeout and setInterval IDs[id].
Increment nesting level by one.
Set task's timer nesting level to nesting level.
Let completionStep be an algorithm step which queues a global task on the timer task source given global to run task.
Set uniqueHandle to the result of running steps after a timeout given global, "setTimeout/setInterval
", timeout,
completionStep.
Set global's map of setTimeout and setInterval IDs[id] to uniqueHandle.
Return id.
Argument conversion as defined by Web IDL (for example, invoking toString()
methods on objects passed as the first argument) happens in the
algorithms defined in Web IDL, before this algorithm is invoked.
So for example, the following rather silly code will result in the log containing "ONE TWO
":
var log = '' ;
function logger( s) { log += s + ' ' ; }
setTimeout({ toString: function () {
setTimeout( "logger('ONE')" , 100 );
return "logger('TWO')" ;
} }, 100 );
To run tasks of several milliseconds back to back without any delay, while still yielding back to the browser to avoid starving the user interface (and to avoid the browser killing the script for hogging the CPU), simply queue the next timer before performing work:
function doExpensiveWork() {
var done = false ;
// ...
// this part of the function takes up to five milliseconds
// set done to true if we're done
// ...
return done;
}
function rescheduleWork() {
var id = setTimeout( rescheduleWork, 0 ); // preschedule next iteration
if ( doExpensiveWork())
clearTimeout( id); // clear the timeout if we don't need it
}
function scheduleWork() {
setTimeout( rescheduleWork, 0 );
}
scheduleWork(); // queues a task to do lots of work
Objects that implement the WindowOrWorkerGlobalScope
mixin have a map of active timers, which is an ordered map,
initially empty. Each key in this map is a unique internal
value that represents a timer, and each value is a
DOMHighResTimeStamp
, representing the expiry time for that timer.
To run steps after a timeout, given a WindowOrWorkerGlobalScope
global, a string orderingIdentifier, a number milliseconds, and a
set of steps completionSteps, perform the following steps. They return a unique
internal value.
Let timerKey be a new unique internal value.
Let startTime be the current high resolution time given global.
Set global's map of active timers[timerKey] to startTime plus milliseconds.
Run the following steps in parallel:
If global is a Window
object, wait until global's associated Document
has been fully
active for a further milliseconds milliseconds (not necessarily
consecutively).
Otherwise, global is a WorkerGlobalScope
object; wait until
milliseconds milliseconds have passed with the worker not suspended (not
necessarily consecutively).
Wait until any invocations of this algorithm that had the same global and orderingIdentifier, that started before this one, and whose milliseconds is less than or equal to this one's, have completed.
Optionally, wait a further implementation-defined length of time.
This is intended to allow user agents to pad timeouts as needed to optimize the power usage of the device. For example, some processors have a low-power mode where the granularity of timers is reduced; on such platforms, user agents can slow timers down to fit this schedule instead of requiring the processor to use the more accurate mode with its associated higher power usage.
Perform completionSteps.
Remove global's map of active timers[timerKey].
Return timerKey.
Run steps after a timeout is meant to be used by other
specifications that want to execute developer-supplied code after a developer-supplied timeout,
in a similar manner to setTimeout()
. (Note, however, it does
not have the nesting and clamping behavior of setTimeout()
.)
Such specifications can choose an orderingIdentifier to ensure ordering within their
specification's timeouts, while not constraining ordering with respect to other specification's
timeouts.
Support in all current engines.
The queueMicrotask(callback)
method must
queue a microtask to invoke
callback with « » and "report
".
The queueMicrotask()
method allows authors to schedule
a callback on the microtask queue. This allows their code to run once the
JavaScript execution context stack is next empty, which happens once all currently
executing synchronous JavaScript has run to completion. This doesn't yield control back to the
event loop, as would be the case when using, for example, setTimeout(f, 0)
.
Authors ought to be aware that scheduling a lot of microtasks has the same performance
downsides as running a lot of synchronous code. Both will prevent the browser from doing its own
work, such as rendering. In many cases, requestAnimationFrame()
or
requestIdleCallback()
is a better choice. In particular, if the goal is to run code
before the next rendering cycle, that is the purpose of requestAnimationFrame()
.
As can be seen from the following examples, the best way of thinking about queueMicrotask()
is as a mechanism for rearranging synchronous
code, effectively placing the queued code immediately after the currently executing synchronous
JavaScript has run to completion.
The most common reason for using queueMicrotask()
is
to create consistent ordering, even in the cases where information is available synchronously,
without introducing undue delay.
For example, consider a custom element firing a load
event, that also
maintains an internal cache of previously-loaded data. A naïve implementation might look
like:
MyElement. prototype. loadData = function ( url) {
if ( this . _cache[ url]) {
this . _setData( this . _cache[ url]);
this . dispatchEvent( new Event( "load" ));
} else {
fetch( url). then( res => res. arrayBuffer()). then( data => {
this . _cache[ url] = data;
this . _setData( data);
this . dispatchEvent( new Event( "load" ));
});
}
};
This naïve implementation is problematic, however, in that it causes its users to experience inconsistent behavior. For example, code such as
element. addEventListener( "load" , () => console. log( "loaded" ));
console. log( "1" );
element. loadData();
console. log( "2" );
will sometimes log "1, 2, loaded" (if the data needs to be fetched), and sometimes log "1,
loaded, 2" (if the data is already cached). Similarly, after the call to loadData()
, it will be inconsistent whether or not the data is set on the
element.
To get a consistent ordering, queueMicrotask()
can be
used:
MyElement. prototype. loadData = function ( url) {
if ( this . _cache[ url]) {
queueMicrotask(() => {
this . _setData( this . _cache[ url]);
this . dispatchEvent( new Event( "load" ));
});
} else {
fetch( url). then( res => res. arrayBuffer()). then( data => {
this . _cache[ url] = data;
this . _setData( data);
this . dispatchEvent( new Event( "load" ));
});
}
};
By essentially rearranging the queued code to be after the JavaScript execution context stack empties, this ensures a consistent ordering and update of the element's state.
Another interesting use of queueMicrotask()
is to
allow uncoordinated "batching" of work by multiple callers. For example, consider a library
function that wants to send data somewhere as soon as possible, but doesn't want to make multiple
network requests if doing so is easily avoidable. One way to balance this would be like so:
const queuedToSend = [];
function sendData( data) {
queuedToSend. push( data);
if ( queuedToSend. length === 1 ) {
queueMicrotask(() => {
const stringToSend = JSON. stringify( queuedToSend);
queuedToSend. length = 0 ;
fetch( "/endpoint" , stringToSend);
});
}
}
With this architecture, multiple subsequent calls to sendData()
within
the currently executing synchronous JavaScript will be batched together into one
fetch()
call, but with no intervening event loop tasks preempting the fetch (as
would have happened with similar code that instead used setTimeout()
).
window.alert(message)
Support in all current engines.
Displays a modal alert with the given message, and waits for the user to dismiss it.
result = window.confirm(message)
Support in all current engines.
Displays a modal OK/Cancel prompt with the given message, waits for the user to dismiss it, and returns true if the user clicks OK and false if the user clicks Cancel.
result = window.prompt(message [, default])
Support in all current engines.
Displays a modal text control prompt with the given message, waits for the user to dismiss it, and returns the value that the user entered. If the user cancels the prompt, then returns null instead. If the second argument is present, then the given value is used as a default.
Logic that depends on tasks or microtasks, such as media elements loading their media data, are stalled when these methods are invoked.
The alert()
and alert(message)
method steps
are:
If we cannot show simple dialogs for this, then return.
If the method was invoked with no arguments, then let message be the empty string; otherwise, let message be the method's first argument.
Set message to the result of normalizing newlines given message.
Set message to the result of optionally truncating message.
Let userPromptHandler be WebDriver BiDi user prompt opened with
this, "alert
", and message.
If userPromptHandler is "none
", then:
Show message to the user, treating U+000A LF as a line break.
Optionally, pause while waiting for the user to acknowledge the message.
Invoke WebDriver BiDi user prompt closed with this,
"alert
", and true.
This method is defined using two overloads, instead of using an
optional argument, for historical reasons. The practical impact of this is
that alert(undefined)
is treated as alert("undefined")
, but alert()
is treated as
alert("")
.
The confirm(message)
method steps are:
If we cannot show simple dialogs for this, then return false.
Set message to the result of normalizing newlines given message.
Set message to the result of optionally truncating message.
Show message to the user, treating U+000A LF as a line break, and ask the user to respond with a positive or negative response.
Let userPromptHandler be WebDriver BiDi user prompt opened with
this, "confirm
", and message.
Let accepted be false.
If userPromptHandler is "none
", then:
Pause until the user responds either positively or negatively.
If the user responded positively, then set accepted to true.
If userPromptHandler is "accept
", then set
accepted to true.
Invoke WebDriver BiDi user prompt closed with this,
"confirm
", and accepted.
Return accepted.
The prompt(message,
default)
method steps are:
If we cannot show simple dialogs for this, then return null.
Set message to the result of normalizing newlines given message.
Set message to the result of optionally truncating message.
Set default to the result of optionally truncating default.
Show message to the user, treating U+000A LF as a line break, and ask the user to either respond with a string value or abort. The response must be defaulted to the value given by default.
Let userPromptHandler be WebDriver BiDi user prompt opened with
this, "prompt
", and message.
Let result be null.
If userPromptHandler is "none
", then:
Pause while waiting for the user's response.
If the user did not abort, then set result to the string that the user responded with.
Otherwise, if userPromptHandler is "accept
", then set
result to the empty string.
Invoke WebDriver BiDi user prompt closed with this,
"prompt
", false if result is null or true otherwise,
and result.
Return result.
To optionally truncate a simple dialog string s, return either s itself or some string derived from s that is shorter. User agents should not provide UI for displaying the elided portion of s, as this makes it too easy for abusers to create dialogs of the form "Important security alert! Click 'Show More' for full details!".
For example, a user agent might want to only display the first 100 characters of a message. Or, a user agent might replace the middle of the string with "…". These types of modifications can be useful in limiting the abuse potential of unnaturally large, trustworthy-looking system dialogs.
We cannot show simple dialogs for a Window
window when the
following algorithm returns true:
If the active sandboxing flag set of window's associated Document
has the sandboxed
modals flag set, then return true.
If window's relevant settings object's origin and window's relevant settings object's top-level origin are not same origin-domain, then return true.
Optionally, return true. (For example, the user agent might give the user the option to ignore all modal dialogs, and would thus abort at this step whenever the method was invoked.)
Return false.
Support in all current engines.
window.print()
Prompts the user to print the page.
The print()
method steps
are:
Let document be this's associated Document
.
If document is not fully active, then return.
If document's unload counter is greater than 0, then return.
If document is ready for post-load tasks, then run the printing steps for document.
Otherwise, set document's print when loaded flag.
User agents should also run the printing steps whenever the user asks for the opportunity to obtain a physical form (e.g. printed copy), or the representation of a physical form (e.g. PDF copy), of a document.
The printing steps for a Document
document are:
The user agent may display a message to the user or return (or both).
For instance, a kiosk browser could silently ignore any invocations of the
print()
method.
For instance, a browser on a mobile device could detect that there are no printers in the vicinity and display a message saying so before continuing to offer a "save to PDF" option.
If the active sandboxing flag set of document has the sandboxed modals flag set, then return.
If the printing dialog is blocked by a Document
's sandbox,
then neither the beforeprint
nor afterprint
events will be fired.
The user agent must fire an event named beforeprint
at the relevant global object of
document, as well as any child navigable in
it.
Firing in children only doesn't seem right here, and some tasks likely need to be queued. See issue #5096.
The beforeprint
event can be used to
annotate the printed copy, for instance adding the time at which the document was printed.
The user agent should offer the user the opportunity to obtain a physical form (or the representation of a physical form) of document. The user agent may wait for the user to either accept or decline before returning; if so, the user agent must pause while the method is waiting. Even if the user agent doesn't wait at this point, the user agent must use the state of the relevant documents as they are at this point in the algorithm if and when it eventually creates the alternate form.
The user agent must fire an event named afterprint
at the relevant global object of
document, as well as any child navigables in
it.
Firing in children only doesn't seem right here, and some tasks likely need to be queued. See issue #5096.
The afterprint
event can be used to
revert annotations added in the earlier event, as well as showing post-printing UI. For
instance, if a page is walking the user through the steps of applying for a home loan, the
script could automatically advance to the next step after having printed a form or other.