search

JavaScript setTimeout() Function: Examples and Usage

The setTimeout() function in JavaScript executes a function after a specified delay. It is one of the most commonly used timing functions in the language, useful for tasks like animations, deferred actions, debouncing user input, or timed events.

In this guide, you’ll learn how setTimeout() works, how to cancel it with clearTimeout(), how to pass arguments, and how to avoid common mistakes.

setTimeout() is not part of the JavaScript language itself. It is provided by the browser’s Web API (or Node.js runtime). The browser handles the timer and pushes the callback into the event queue once the delay expires.

Basic Usage of setTimeout()

The setTimeout() function takes two parameters: the callback function to execute and the delay in milliseconds:

setTimeout(function, delay);

Here is an example:

setTimeout(function() {
    console.log('This message is displayed after 2 seconds');
}, 2000);

The message will be logged to the console after a 2-second delay.

You can also use an arrow function for a more concise syntax:

setTimeout(() => {
    console.log('Arrow function after 2 seconds');
}, 2000);

Using Named Functions with setTimeout()

Instead of passing an anonymous function, you can pass a named function reference:

function showMessage() {
    console.log('This message is displayed after 3 seconds');
}
setTimeout(showMessage, 3000);

The showMessage function is executed after a 3-second delay. Note that you pass showMessage without parentheses – passing showMessage() would execute it immediately instead of after the delay.

Passing Arguments to setTimeout()

You can pass additional arguments to setTimeout() after the delay. These are forwarded to the callback function:

function greet(name, role) {
    console.log(`Hello, ${name}! You are a ${role}.`);
}

setTimeout(greet, 2000, 'Alice', 'developer');

After 2 seconds, this logs: Hello, Alice! You are a developer.

This is cleaner than wrapping the call in an anonymous function, though both approaches work:

// Also valid, but more verbose
setTimeout(() => {
    greet('Alice', 'developer');
}, 2000);

Canceling a Timeout with clearTimeout()

setTimeout() returns a numeric ID that identifies the timer. You can pass this ID to clearTimeout() to cancel the scheduled execution before it runs:

const timeoutID = setTimeout(() => {
    console.log('This message will not be displayed');
}, 4000);

clearTimeout(timeoutID);

The timeout is canceled before the callback fires, so the message is never logged. This is useful for scenarios like canceling a pending API call when a user navigates away, or resetting a debounce timer.

setTimeout with Zero Delay

Setting the delay to 0 does not execute the function immediately. It schedules the callback to run after the current call stack is empty:

console.log('First');

setTimeout(() => {
    console.log('Third - runs after the stack is clear');
}, 0);

console.log('Second');

Output:

First
Second
Third - runs after the stack is clear

This happens because setTimeout() places the callback in the task queue, and the event loop only processes it after all synchronous code finishes. This pattern is sometimes used to defer work until the browser has finished rendering.

Browsers enforce a minimum delay of 4ms for nested setTimeout() calls (after the 5th consecutive nesting). This means setTimeout(fn, 0) actually runs after at least 4ms in deeply nested scenarios. For truly immediate async execution, use queueMicrotask() or Promise.resolve().then() instead.

Recursive setTimeout vs setInterval

If you need to run a function repeatedly, you might reach for setInterval(). However, recursive setTimeout() gives you more control:

// Using setInterval - fires every 2 seconds regardless of execution time
const intervalID = setInterval(() => {
    console.log('Interval tick');
}, 2000);

// Using recursive setTimeout - waits for execution to finish before scheduling next
function tick() {
    console.log('Timeout tick');
    setTimeout(tick, 2000);
}
tick();

The key difference: setInterval() schedules the next call from the start of the current one, while recursive setTimeout() schedules it from the end. If the callback takes time to execute (e.g., a network request), recursive setTimeout() guarantees a consistent gap between calls.

To stop a recursive setTimeout(), use a condition or store the ID:

let count = 0;

function countUp() {
    count++;
    console.log(count);
    if (count < 5) {
        setTimeout(countUp, 1000);
    }
}
countUp();

Common Mistakes with setTimeout()

Calling the Function Instead of Passing a Reference

This is the most common mistake. Using parentheses executes the function immediately:

// Wrong - greet() runs immediately, not after 2 seconds
setTimeout(greet(), 2000);

// Correct - passes a reference to greet
setTimeout(greet, 2000);

Assuming the Delay Is Exact

The delay is a minimum, not a guarantee. If the main thread is busy, the callback waits until the thread is free:

setTimeout(() => {
    console.log('This may run later than 100ms');
}, 100);

// Heavy synchronous work blocks the callback
for (let i = 0; i < 1000000000; i++) {}

Losing “this” Context

When passing a method as a callback, this may not point to the expected object:

const user = {
    name: 'Alice',
    greet() {
        console.log(`Hello, ${this.name}`);
    }
};

// Wrong - "this" will be undefined or the global object
setTimeout(user.greet, 1000);

// Fix 1 - wrap in an arrow function
setTimeout(() => user.greet(), 1000);

// Fix 2 - use bind
setTimeout(user.greet.bind(user), 1000);

Live Example of setTimeout()

The following live example uses setTimeout() to display a message after a 2-second delay when the “Start Timer” button is clicked. If the “Cancel Timer” button is clicked before the timeout completes, clearTimeout() stops the timer and displays “Timer canceled” instead.

The code for this example:

HTML:

<button id="startButton">Start Timer</button>
<button id="cancelButton">Cancel Timer</button>
<div id="message"></div>

JavaScript:

document.addEventListener('DOMContentLoaded', () => {
    let timeoutID;
    const messageDiv = document.getElementById('message');
    const startButton = document.getElementById('startButton');

    startButton.addEventListener('click', () => {
        startButton.classList.add('active');
        timeoutID = setTimeout(() => {
            messageDiv.textContent = 'This message is displayed after 2 seconds';
            startButton.classList.remove('active');
        }, 2000);
    });

    document.getElementById('cancelButton').addEventListener('click', () => {
        clearTimeout(timeoutID);
        messageDiv.textContent = 'Timer canceled';
        startButton.classList.remove('active');
    });
});

FAQs

Common questions about setTimeout() in JavaScript:

What is the difference between setTimeout() and setInterval()?
setTimeout() executes a function once after a specified delay. setInterval() executes a function repeatedly at a fixed interval until you call clearInterval(). For repeated execution with more control, consider using recursive setTimeout() instead of setInterval(), as it guarantees a consistent gap between each execution.
Why does setTimeout(fn, 0) not execute immediately?
Even with a 0ms delay, the callback is placed in the task queue and must wait for the current call stack to empty before executing. This means all synchronous code runs first. Additionally, browsers enforce a minimum delay of 4ms for deeply nested setTimeout() calls (after the 5th level).
How do I pass arguments to the setTimeout callback function?
You can pass arguments after the delay parameter: setTimeout(myFunction, 2000, arg1, arg2). These extra arguments are forwarded to the callback function. Alternatively, you can wrap the call in an arrow function: setTimeout(() => myFunction(arg1, arg2), 2000).
Is setTimeout() accurate for measuring time?
No. The delay is a minimum wait time, not a precise timer. If the main thread is busy with other tasks, the callback will be delayed further. For accurate timing (e.g., animations), use requestAnimationFrame(). For measuring elapsed time, use performance.now() instead of relying on setTimeout() delays.
Can I use async/await with setTimeout()?
setTimeout() does not return a Promise, so you cannot await it directly. However, you can wrap it in a Promise to make it awaitable:
function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function run() {
    console.log('Start');
    await delay(2000);
    console.log('2 seconds later');
}

Summary

setTimeout() schedules a function to run after a specified delay. It returns a timer ID that you can pass to clearTimeout() to cancel the execution before it fires.

Key points to remember: the delay is a minimum wait time (not a guarantee), you should pass function references without parentheses, and this context can be lost when passing methods as callbacks. For repeated execution, recursive setTimeout() is often preferable to setInterval().

For more JavaScript fundamentals, check out the guides on DOM manipulation and object methods and “this”.

Join the Discussion
0 Comments  ]

Leave a Comment

To add code, use the buttons below. For instance, click the PHP button to insert PHP code within the shortcode. If you notice any typos, please let us know!

Savvy WordPress Development official logo