setTimeout(): void
When writing JavaScript code, you might want to delay the execution of a function.
This is the job of setTimeout. You specify a callback function to execute later, and a value expressing how later you want it to run, in milliseconds:
setTimeout(() => { // runs after 2 seconds }, 2000); setTimeout(() => { // runs after 50 milliseconds }, 50);
This syntax defines a new function. You can call whatever other function you want in there, or you can pass an existing function name, and a set of parameters:
const myFunction = (firstParam, secondParam) => { // do something }; // runs after 2 seconds setTimeout(myFunction, 2000, firstParam, secondParam);
setTimeout returns a Timeout instance in Node.js, whereas in browsers it returns a numeric timer ID. This object or ID can be used to cancel the scheduled function execution:
const timeout = setTimeout(() => { // should run after 2 seconds }, 2000); // I changed my mind clearTimeout(timeout);
If you specify the timeout delay to 0, the callback function will be executed as soon as possible, but after the current function execution:
setTimeout(() => { console.log('after '); }, 0); console.log(' before ');
This code will print
before after
This is especially useful to avoid blocking the CPU on intensive tasks and let other functions be executed while performing a heavy calculation, by queuing functions in the scheduler.
Some browsers (IE and Edge) implement a
setImmediate()method that does this same exact functionality, but it's not standard and unavailable on other browsers. But it's a standard function in Node.js.
setInterval(): void
setInterval is a function similar to setTimeout, with a difference: instead of running the callback function once, it will run it forever, at the specific time interval you specify (in milliseconds):
setInterval(() => { // runs every 2 seconds }, 2000);
The function above runs every 2 seconds unless you tell it to stop, using clearInterval, passing it the interval id that setInterval returned:
const timeout = setInterval(() => { // runs every 2 seconds }, 2000); clearInterval(timeout);
It's common to call clearInterval inside the setInterval callback function, to let it auto-determine if it should run again or stop. For example this code runs something unless App.somethingIWait has the value arrived:
const interval = setInterval(() => { if (App.somethingIWait === 'arrived') { clearInterval(interval); } // otherwise do things }, 100);
setInterval starts a function every n milliseconds, without any consideration about when a function finished its execution.
If a function always takes the same amount of time, it's all fine:
0 1000 2000 3000 | | | | | | | | | [██████████] | | | [exe script] | | | [██████████] | | | | [██████████] | | | [exe script] | | | [██████████] | | | | [██████████] | | | [exe script] | | | [██████████] |__________|___________|___________|____
Maybe the function takes different execution times, depending on network conditions for example:
0 1000 2000 3000 | | | | | | | | | [██████████] | | | [exe script] | | | [██████████] | | | | [████████████████████] | | [ execute script ] | | [████████████████████] | | | [██████████] | | | [exe script] | | | [██████████] |__________|___________|___________|____
And maybe one long execution overlaps the next one:
0 1000 2000 3000 4000 | | | | | | [████████████████████] | | | [ execute script ] | | | [████████████████████] | | | [███████████████████████████] | | [ execute script ] | | [███████████████████████████] | | | | [██████████████] | | | [execute script] | | | [██████████████] |__________|___________|___________|___________|__
To avoid this, you can schedule a recursive setTimeout to be called when the callback function finishes:
const myFunction = () => { // do something setTimeout(myFunction, 1000); }; setTimeout(myFunction, 1000);
to achieve this scenario:
0 1000 2000 3000 | | | | | [█████████████] | [█████████████] | [ exec script ]>──1s──<[ exec script ] | [█████████████] | [█████████████] | | | | |__________|____________|___________|__________
setTimeout and setInterval are available in Node.js, through the Timers module.
Node.js also provides setImmediate(), which schedules a callback to execute during the check phase of the event loop. Unlike setTimeout(() => {}, 0), it is not generally equivalent because their callbacks are executed in different phases of the event loop and their execution order depends on the execution context.