JavaScript's setTimeout function is widely used to schedule tasks to be executed after a specified delay. However, understanding how such a function can be built from scratch helps you deepen your grasp of JavaScript's asynchronous nature. In this blog, we'll explore a polyfill for setTimeout using a custom implementation, mySetTimeout, and its counterpart, myClearTimeout.
Here's the code for our polyfill:
function createSetTimeout() {
let timerId = 0;
let timerMap = {};
function mySetTimeout(cb, time, ...args) {
var id = timerId++;
timerMap[id] = true;
let start = Date.now();
function triggerCallback() {
if (!timerMap[id]) return;
if (Date.now() > start + time) {
cb.apply(this, args);
} else {
requestIdleCallback(triggerCallback);
}
}
requestIdleCallback(triggerCallback);
return id;
}
function myClearTimeout(id) {
delete timerMap[id];
}
return {
mySetTimeout,
myClearTimeout
}
}
const {
mySetTimeout,
myClearTimeout
} = createSetTimeout();
let timer = mySetTimeout((...args) => {
console.log("this is setTimeout.....", ...args);
}, 1000, "satish", "shriwas");Step-by-Step Explanation
1. createSetTimeout Function:
This function serves as the main setup for our polyfill. It encapsulates the logic and maintains state using closures. Inside this function:
timerIdis initialized to0. It will be used to generate unique IDs for each timer.timerMapis an object that stores active timers. It helps manage and clear timers when needed.
2. mySetTimeout Function:
This function mimics the behavior of setTimeout. Here's how it works:
- Timer ID Management:
- A unique
idis generated for each timer usingtimerId++. - The timer ID is stored in
timerMap, marked astrueto indicate that it's active. - Time Calculation:
startcaptures the current time usingDate.now(). This value is used to calculate the elapsed time.- Callback Execution (
triggerCallback): - This function is responsible for executing the callback function
cbwhen the specified time has passed. - It checks if the current time (
Date.now()) is greater than the start time plus the specified delay (time). If true, it triggers the callback usingcb.apply(this, args)to ensure the correct context and arguments are passed. - If the time hasn't elapsed yet, it is used
requestIdleCallbackto recursively check again when the browser is idle. - Returning the Timer ID:
- The function returns the unique
idgenerated for the timer. This ID can be used to clear the timer later.
3. myClearTimeout Function:
This function allows you to clear a timer before it executes, just like the native clearTimeout.
- It takes a timer ID as an argument and deletes the corresponding entry from
timerMap. This prevents the callback from being executed.
4. Using mySetTimeout and myClearTimeout:
Finally, you can use mySetTimeout to schedule tasks, and myClearTimeout to cancel them. In the example provided:
let timer = mySetTimeout((...args) => {
console.log("this is setTimeout.....", ...args);
}, 1000, "satish", "shriwas");A timer is set to log a message to the console after 1 second, along with the arguments "satish" and "shriwas".
Key Points:
requestIdleCallback: This method is used to defer the execution oftriggerCallbackuntil the browser is idle, making it more efficient for low-priority background tasks. However, it might not be as precise as the nativesetTimeout, making this polyfill better suited for non-critical timing tasks.- Closure: The polyfill uses closures to maintain the state (
timerIdandtimerMap) across multiple calls tomySetTimeoutandmyClearTimeout.
Conclusion:
This custom polyfill setTimeout demonstrates how you can implement asynchronous behavior using JavaScript's built-in functions. While the native setTimeout is optimized and should be your go-to choice, understanding and implementing such polyfills can significantly improve your JavaScript skills, especially when dealing with asynchronous code and browser event loops.
This implementation provides a basic framework that you can expand and adapt based on your needs. Happy coding!
In Plain English ๐
Thank you for being a part of the In Plain English community! Before you go:
- Be sure to clap and follow the writer ๏ธ๐๏ธ๏ธ
- Follow us: X | LinkedIn | YouTube | Discord | Newsletter
- Visit our other platforms: CoFeed | Differ
- More content at PlainEnglish.io