clearTimeout()

Cancels a pending timer created by setTimeout() before its callback runs.

Signature
clearTimeout(timeout)
  • Added in Node.js v0.0.1

Parameters

ParameterTypeDescription
$timeout<Timeout> | <string> | <number>A Timeout object as returned by setTimeout() or the primitive of the Timeout object as a string or a number.

Return value

<undefined>Nothing.

Errors

Does not throw for unknown, undefined or already-cleared values; it is a no-op.

clearTimeout() cancels a timer that has not fired yet. Pass it the Timeout object setTimeout() returned, or the numeric/string primitive from timeout[Symbol.toPrimitive]() — that primitive is only valid in the thread that created the timer.

When to reach for it

  • Debouncing: cancel the pending call and schedule a new one on every event.
  • Deadline guards: clear the loser as soon as the real work settles.
  • Teardown: cancel outstanding timers in a close() method or on SIGTERM.

What trips people up

It is forgiving to the point of hiding bugs. Calling it twice, calling it after the callback already ran, or calling it with undefined all do nothing and report nothing — so a typo in the variable holding the handle fails silently and the timer still fires. If a timer you expected to cancel keeps firing, check that you captured the return value and are not clearing a stale copy.

Clearing does not run the callback and does not reject anything. If a promise was waiting on that timer, it stays pending forever unless you settle it yourself.

An uncleared pending timeout also keeps the process alive until it fires, which is why a forgotten deadline timer makes a fast script sit idle before exiting.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Debounce a search-as-you-type handler
  • Cancel a request timeout once the response arrives
  • Cancel scheduled retries during graceful shutdown
  • Stop a delayed UI or log message when the user acts first

Frequently asked questions

Why is my timer still firing after I called clearTimeout?

Almost always because the handle passed in is not the one that is pending — a reassigned variable, a stale copy, or undefined. clearTimeout() never throws or reports failure, so a wrong argument is indistinguishable from a successful cancel; log the handle before clearing to confirm.

Does clearTimeout run the callback or reject the promise?

No. The callback is discarded and nothing is invoked, so a promise that was going to be resolved by that callback stays pending forever. Settle it yourself, or use the AbortSignal option in node:timers/promises.

Is it safe to call clearTimeout twice or on a timer that already ran?

Yes, both are harmless no-ops, as is calling it with undefined or null. That makes it safe to call unconditionally in cleanup paths such as finally blocks and close() methods.

More examples

Debounce built on clearTimeout

Only 'saved: hello' is printed, roughly 200ms after the last call. Each new call clears the previous timer, so the first three are discarded before they ever fire — and cancel() makes the debounce safe to tear down.

Example · javascript
function debounce(fn, wait) {
  let timer = null;
  const debounced = (...args) => {
    clearTimeout(timer);          // cancel the previous, still-pending call
    timer = setTimeout(() => {
      timer = null;
      fn(...args);
    }, wait);
  };
  debounced.cancel = () => {
    clearTimeout(timer);
    timer = null;
  };
  return debounced;
}

const save = debounce((text) => console.log('saved:', text), 200);

save('h');
save('he');
save('hell');
save('hello');   // only this one survives

Clearing the loser of a timeout race

Every exit path — success, timeout, and socket error — clears the guard. Miss one and the process sits idle for the remaining 2 seconds after the work is done, because the pending timer still holds the event loop open.

Example · javascript
const http = require('node:http');

function get(url, ms) {
  return new Promise((resolve, reject) => {
    const req = http.get(url, (res) => {
      clearTimeout(guard);        // response arrived; drop the deadline
      let body = '';
      res.setEncoding('utf8');
      res.on('data', (c) => { body += c; });
      res.on('end', () => resolve(body));
    });

    const guard = setTimeout(() => {
      req.destroy(new Error(`no response in ${ms}ms`));
      reject(new Error('timeout'));
    }, ms);

    req.on('error', (err) => {
      clearTimeout(guard);
      reject(err);
    });
  });
}

console.log(await get('http://127.0.0.1:8080/health', 2000));

Cancelling by the primitive id

Demonstrates that clearTimeout accepts the numeric primitive as well as the Timeout object, which is useful when a handle has to be stored somewhere that only holds numbers. The last two lines show the silent no-op on a bad argument.

Example · javascript
const t = setTimeout(() => console.log('nope'), 30);

const id = t[Symbol.toPrimitive]();   // v14.9.0, v12.19.0
console.log('primitive id is a number:', typeof id === 'number');

clearTimeout(id);
console.log('cleared by primitive');

clearTimeout(undefined);
console.log('clearTimeout(undefined) is a no-op');

Discussion

  • Be the first to comment on this lesson.