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.
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
.
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.
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.