Skip to content

clearAllTimeout() #509

@jsartisan

Description

@jsartisan

Info

difficulty: easy
title: clearAllTimeout()
type: question
template: javascript
tags: javascript

Question

Implement a clearAllTimeout() function that cancels all active timers created with setTimeout(). This is particularly useful for cleaning up timers before page transitions or when you need to cancel all pending asynchronous operations.

Requirements

  1. Track all timers – Keep track of every timer ID created by setTimeout()
  2. Clear all timers – Provide a function to cancel all active timers at once
  3. Preserve original API – Maintain the same interface for setTimeout() and clearTimeout()
  4. Handle edge cases – Work correctly when no timers exist or when called multiple times
  5. Global functionality – Replace the global setTimeout() and clearTimeout() functions

Key Behaviors

  • Timer tracking – Store all timer IDs internally for batch clearing
  • Original functionalitysetTimeout() and clearTimeout() work exactly as before
  • Batch clearingclearAllTimeout() cancels all pending timers
  • No side effects – Clearing doesn't affect the original timer API behavior
  • Memory management – Properly clean up timer references after clearing

Example

// Replace global setTimeout and clearTimeout
setTimeout(func1, 10000);
setTimeout(func2, 10000);
setTimeout(func3, 10000);

// All 3 functions are scheduled 10 seconds later
clearAllTimeout();

// All scheduled tasks are cancelled

// Original API still works
const timerId = setTimeout(() => console.log('delayed'), 1000);
clearTimeout(timerId); // This specific timer is cleared

Key Challenge

The function must intercept and track all setTimeout() calls while preserving the original API behavior and providing a way to clear all timers at once.

Template (JavaScript)

javascript.template.md

// Replace the global setTimeout and clearTimeout
window.setTimeout = function(callback, delay) {
  // TODO: Implement me
};

window.clearTimeout = function(timerId) {
  // TODO: Implement me
};

export function clearAllTimeout() {
  // TODO: Implement me
}
import { clearAllTimeout } from './index';

describe('clearAllTimeout', () => {
  beforeEach(() => {
    jest.useFakeTimers();
  });

  afterEach(() => {
    jest.clearAllTimers();
    jest.useRealTimers();
  });

  it('should clear all active timers', () => {
    const callback1 = jest.fn();
    const callback2 = jest.fn();
    const callback3 = jest.fn();

    setTimeout(callback1, 1000);
    setTimeout(callback2, 2000);
    setTimeout(callback3, 3000);

    clearAllTimeout();

    jest.advanceTimersByTime(5000);

    expect(callback1).not.toHaveBeenCalled();
    expect(callback2).not.toHaveBeenCalled();
    expect(callback3).not.toHaveBeenCalled();
  });

  it('should work when no timers exist', () => {
    expect(() => clearAllTimeout()).not.toThrow();
  });

  it('should preserve original setTimeout behavior', () => {
    const callback = jest.fn();
    const timerId = setTimeout(callback, 1000);

    expect(typeof timerId).toBe('number');
    
    jest.advanceTimersByTime(1000);
    expect(callback).toHaveBeenCalled();
  });

  it('should preserve original clearTimeout behavior', () => {
    const callback = jest.fn();
    const timerId = setTimeout(callback, 1000);

    clearTimeout(timerId);

    jest.advanceTimersByTime(2000);
    expect(callback).not.toHaveBeenCalled();
  });

  it('should handle mixed clearTimeout and clearAllTimeout', () => {
    const callback1 = jest.fn();
    const callback2 = jest.fn();
    const callback3 = jest.fn();

    const timerId1 = setTimeout(callback1, 1000);
    setTimeout(callback2, 2000);
    const timerId3 = setTimeout(callback3, 3000);

    clearTimeout(timerId1);
    clearAllTimeout();

    jest.advanceTimersByTime(5000);

    expect(callback1).not.toHaveBeenCalled();
    expect(callback2).not.toHaveBeenCalled();
    expect(callback3).not.toHaveBeenCalled();
  });

  it('should work with multiple clearAllTimeout calls', () => {
    const callback = jest.fn();
    setTimeout(callback, 1000);

    clearAllTimeout();
    clearAllTimeout();

    jest.advanceTimersByTime(2000);
    expect(callback).not.toHaveBeenCalled();
  });

  it('should handle timers with different delays', () => {
    const callback1 = jest.fn();
    const callback2 = jest.fn();
    const callback3 = jest.fn();

    setTimeout(callback1, 100);
    setTimeout(callback2, 500);
    setTimeout(callback3, 1000);

    clearAllTimeout();

    jest.advanceTimersByTime(2000);

    expect(callback1).not.toHaveBeenCalled();
    expect(callback2).not.toHaveBeenCalled();
    expect(callback3).not.toHaveBeenCalled();
  });

  it('should handle immediate timers (delay 0)', () => {
    const callback = jest.fn();
    setTimeout(callback, 0);

    clearAllTimeout();

    jest.advanceTimersByTime(100);
    expect(callback).not.toHaveBeenCalled();
  });
});

Template (TypeScript)

typescript.template.md

// Replace the global setTimeout and clearTimeout
(window as any).setTimeout = function(callback: Function, delay?: number): number {
  // TODO: Implement me
};

(window as any).clearTimeout = function(timerId: number): void {
  // TODO: Implement me
};

export function clearAllTimeout(): void {
  // TODO: Implement me
}
import { clearAllTimeout } from './index';

describe('clearAllTimeout', () => {
  beforeEach(() => {
    jest.useFakeTimers();
  });

  afterEach(() => {
    jest.clearAllTimers();
    jest.useRealTimers();
  });

  it('should clear all active timers', () => {
    const callback1 = jest.fn();
    const callback2 = jest.fn();
    const callback3 = jest.fn();

    setTimeout(callback1, 1000);
    setTimeout(callback2, 2000);
    setTimeout(callback3, 3000);

    clearAllTimeout();

    jest.advanceTimersByTime(5000);

    expect(callback1).not.toHaveBeenCalled();
    expect(callback2).not.toHaveBeenCalled();
    expect(callback3).not.toHaveBeenCalled();
  });

  it('should work when no timers exist', () => {
    expect(() => clearAllTimeout()).not.toThrow();
  });

  it('should preserve original setTimeout behavior', () => {
    const callback = jest.fn();
    const timerId = setTimeout(callback, 1000);

    expect(typeof timerId).toBe('number');
    
    jest.advanceTimersByTime(1000);
    expect(callback).toHaveBeenCalled();
  });

  it('should preserve original clearTimeout behavior', () => {
    const callback = jest.fn();
    const timerId = setTimeout(callback, 1000);

    clearTimeout(timerId);

    jest.advanceTimersByTime(2000);
    expect(callback).not.toHaveBeenCalled();
  });

  it('should handle mixed clearTimeout and clearAllTimeout', () => {
    const callback1 = jest.fn();
    const callback2 = jest.fn();
    const callback3 = jest.fn();

    const timerId1 = setTimeout(callback1, 1000);
    setTimeout(callback2, 2000);
    const timerId3 = setTimeout(callback3, 3000);

    clearTimeout(timerId1);
    clearAllTimeout();

    jest.advanceTimersByTime(5000);

    expect(callback1).not.toHaveBeenCalled();
    expect(callback2).not.toHaveBeenCalled();
    expect(callback3).not.toHaveBeenCalled();
  });

  it('should work with multiple clearAllTimeout calls', () => {
    const callback = jest.fn();
    setTimeout(callback, 1000);

    clearAllTimeout();
    clearAllTimeout();

    jest.advanceTimersByTime(2000);
    expect(callback).not.toHaveBeenCalled();
  });

  it('should handle timers with different delays', () => {
    const callback1 = jest.fn();
    const callback2 = jest.fn();
    const callback3 = jest.fn();

    setTimeout(callback1, 100);
    setTimeout(callback2, 500);
    setTimeout(callback3, 1000);

    clearAllTimeout();

    jest.advanceTimersByTime(2000);

    expect(callback1).not.toHaveBeenCalled();
    expect(callback2).not.toHaveBeenCalled();
    expect(callback3).not.toHaveBeenCalled();
  });

  it('should handle immediate timers (delay 0)', () => {
    const callback = jest.fn();
    setTimeout(callback, 0);

    clearAllTimeout();

    jest.advanceTimersByTime(100);
    expect(callback).not.toHaveBeenCalled();
  });
});

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions