JavaScript

setTimeout in JavaScript - Syntax & Examples

Guide to setTimeout() in JavaScript - delayed execution, passing arguments, clearTimeout, and practical async patterns.

Syntax

const timeoutId = setTimeout(callback, delay, ...args);
ParameterTypeDescription
callbackFunctionThe function to execute after the delay
delayNumberMilliseconds to wait (default: 0)
...argsAnyOptional arguments passed to the callback

Returns a numeric timeoutId that can be passed to clearTimeout() to cancel the scheduled execution.

Basic Examples

// Simple delayed message
setTimeout(() => {
  console.log('This runs after 2 seconds');
}, 2000);

// With arguments
setTimeout((name, role) => {
  console.log(`Hello ${name}, you are a ${role}`);
}, 1000, 'Alice', 'developer');

// Zero delay - runs after current call stack clears
setTimeout(() => {
  console.log('Runs after synchronous code');
}, 0);
console.log('This prints first');

Cancelling with clearTimeout

const id = setTimeout(() => {
  console.log('This will NOT run');
}, 5000);

// Cancel before it fires
clearTimeout(id);

setTimeout with this and Classes

One of the most common pitfalls with setTimeout is losing the this context. Here are three solutions:

Problem - Lost Context

class Timer {
  constructor() {
    this.seconds = 0;
  }
  start() {
    // BUG: 'this' is undefined inside setTimeout
    setTimeout(function() {
      this.seconds++;  // TypeError!
    }, 1000);
  }
}

Fix 1 - Arrow Function (recommended)

class Timer {
  constructor() { this.seconds = 0; }
  start() {
    // Arrow function inherits 'this' from parent scope
    setTimeout(() => {
      this.seconds++;  // Works!
      console.log(this.seconds);
    }, 1000);
  }
}

Fix 2 - bind()

start() {
  setTimeout(function() {
    this.seconds++;
  }.bind(this), 1000);
}

Fix 3 - Variable Capture

start() {
  const self = this;
  setTimeout(function() {
    self.seconds++;
  }, 1000);
}

Practical Patterns

Debounce

function debounce(fn, delay) {
  let timer;
  return function(...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}

// Usage: only fire after user stops typing
const search = debounce((query) => {
  fetch(`/api/search?q=${query}`);
}, 300);

input.addEventListener('input', (e) => search(e.target.value));

Polling

function poll(fn, interval) {
  async function check() {
    const done = await fn();
    if (!done) setTimeout(check, interval);
  }
  check();
}

// Check order status every 5 seconds
poll(async () => {
  const res = await fetch('/api/order/123');
  const data = await res.json();
  if (data.status === 'shipped') {
    showNotification('Your order shipped!');
    return true;  // stop polling
  }
  return false;
}, 5000);

Retry with Exponential Backoff

async function fetchWithRetry(url, retries = 3) {
  for (let i = 0; i < retries; i++) {
    try {
      return await fetch(url);
    } catch (err) {
      if (i === retries - 1) throw err;
      const delay = Math.pow(2, i) * 1000; // 1s, 2s, 4s
      await new Promise(r => setTimeout(r, delay));
    }
  }
}

setTimeout vs setInterval

FeaturesetTimeoutsetInterval
ExecutionOnce after delayRepeats every interval
CancelclearTimeout(id)clearInterval(id)
DriftNone (single shot)Can accumulate
Recursive alternativesetTimeout inside callbackN/A

Pro tip: Recursive setTimeout is often preferred over setInterval because it guarantees the delay between the end of one execution and the start of the next, preventing overlap if the callback takes longer than the interval.

Last updated: 2026 • Browse all courses