Keeping Track of Timers

The primary challenge here is how to maintain a list of all active timers in the window object. Our aim is to be able to loop through this list and cancel each timer using window.clearTimeout.

Utilizing Sets for Efficient Tracking

We'll use a Set, aptly named timers, to hold timer IDs. Sets are a data structure that allow us to enjoy near-constant time for both insertion and deletion.

JAVASCRIPT
1const timers = new Set();

Storing Native Functions

Before we create custom wrapper functions around window.setTimeout and window.clearTimeout, it's essential to save the native implementations. We'll store these in variables named window.nativeSetTimeout and window.nativeClearTimeout.

JAVASCRIPT
1const timers = new Set();
2window.nativeSetTimeout = window.setTimeout;
3window.nativeClearTimeout = window.clearTimeout;

Crafting Wrapper Functions for Timer Management

Now let's get creative! We can write custom wrapper functions around window.setTimeout and window.clearTimeout. These wrappers will have an additional duty: tracking new timers. When a new timer is created, its ID will be added to our Set. Similarly, we'll remove IDs when timers are cleared or completed.

JAVASCRIPT
1window.setTimeout = (cb, time, ...args) => {
2  const cbWrapper = () => {
3    cb(...args);
4    // No longer need to track once completed
5    timers.delete(id);
6  };
7  const id = window.nativeSetTimeout(cbWrapper, time);
8  timers.add(id);
9  return id;
10};
11
12window.clearTimeout = (id) => {
13  window.nativeClearTimeout(id);
14  timers.delete(id);
15};

In these wrapper functions, we use the native implementations to actually set and clear the timeouts. Our added functionality is simply to manage the timer IDs using the timers Set. This way, when you need to clear all timeouts, you can easily loop through this Set and clear each one.