Understanding setTimeout() in JavaScript

Hero image for Understanding setTimeout() in JavaScript. Image by Szabo Viktor.
Hero image for 'Understanding setTimeout() in JavaScript.' Image by Szabo Viktor.

The setTimeout function is a fundamental part of JavaScript, widely used for scheduling tasks to be executed after a defined period of delay. In frontend development, understanding how to use setTimeout, and especially how to clean these back up again is crucial.


What is setTimeout()?

setTimeout is a global JavaScript function that allows you to execute a piece of code once after a specified delay. It's part of the Window interface in the browser environment, which means it is widely available in frontend development (although not on initial load if your application is SSR'd).

Basic Syntax

setTimeout(function, delayInMilliseconds, ...args)
  • function: The function to execute after the delay.
  • delayInMilliseconds: The time to wait before executing the function (in milliseconds).
  • ...args: Any additional arguments you want to pass into the function.

Using setTimeout in Vanilla JavaScript

In a basic/vanilla JavaScript context, setTimeout's use is simple and easy to understand:

const sayHello = (): void => {  console.log('Hello, world!');};setTimeout(sayHello, 2000);  //=> 'Hello, world!' after 2 seconds

Here, we will see Hello, world! output to the console after a two second delay (2000 milliseconds). The timer starts immediately once the line setTimeout(sayHello, 2000) is executed, triggering the sayHello function two seconds later.

Because we're not setting any context in this example, that would be two seconds after the script is loaded by the browser.


setTimeout in React

In React, using setTimeout is a very tiny bit more complicated:

  • Cleanup:

    In React, especially when using hooks like useEffect, cleanup becomes really important to avoid side effects on unmounted components. If you have a timeout underway, and the component is then unmounted, you need to make sure that the process of unmounting also cancels the timeout.
  • State and Timing

    : In React, if setTimeout is used to update the state, you need to be careful of how you align these updates with the component lifecycle. It's very easy to find functionality getting triggered multiple times as multiple timeouts are set off an item of state.

Here's a quick example:

useEffect(() => {  const timer = setTimeout(() => {    console.log('Hello, world!');  }, 3000);  // make sure that the timer is cleaned up in the return  return () => clearTimeout(timer);}, []);

Here, I'm using setTimeout within a useEffect to create a timer. With an empty dependency array ([]), the hook only triggers once, at the point the component mounts. The timer is assigned to a variable (timer), which allows us to include a cleanup function (clearTimeout) on it within the useEffect return. This ensures that any incomplete instances of timer are cancelled at the point that the component unmounts, which prevents potential bugs and/or memory leaks within your application.


A Warning About Accuracy

Whilst setTimeout is widely used for timing operations in JavaScript, it is important to understand that its accuracy cannot be relied on totally, partially because it can be affected by JavaScript's singlethreaded nature.

As you may already know, JavaScript executes code in a single thread, meaning that tasks are executed one at a time. When you set a timeout, you're scheduling a task to run after a certain period, which means your task gets placed into the JavaScript event loop and queued. When the timer is up, if the event loop is busy with other tasks (like longrunning computations, other timeouts, or handling DOM events), then your timeout has to wait its turn.

As a result of this, the actual execution time of the timeout's callback function might be delayed past the period you've specified. This behaviour is especially noticeable with short timeout durations or in a heavily loaded application where the event loop is frequently occupied.

It's also worth mentioning that browsers implement a minimum delay for setTimeout, which can also cause deviations from your specified timeout duration. This is written into the HTML Standard as a way to optimise performance and reduce the potential negative effects of very short or nested timeouts.


The Wrap‑Up

setTimeout is a versatile tool in JavaScript, but which needs a little bit more attention when used in a component lifecycle environment like React. Be a little careful: I see setTimeout used a lot by junior developers where using event listeners (for example: to detect when an animation sequence has completed) might make more sense, and would avoid issues where things become out of sync.


Categories:

  1. Adaptive Development
  2. Cross‑Browser Compatibility
  3. Development
  4. Front‑End Development
  5. JavaScript
  6. Responsive Development