Implementing a Custom `setTimeout` in JavaScript



Implementing a custom setTimeout function in JavaScript involves creating a function that mimics the behavior of the native setTimeout function, which executes a callback function after a specified delay. This can be particularly useful for understanding how asynchronous operations and event loops work in JavaScript. we'll create a custom setTimeout function using JavaScript's built-in capabilities.


What is setTimeout?

setTimeout is a native JavaScript function that executes a specified function or piece of code once after a certain delay (in milliseconds).

Real Interview Insights

Interviewers might ask you to:

  • Implement a custom version of setTimeout.
  • Ensure the function mimics the behavior of the native setTimeout.
  • Handle edge cases, such as cancelling the timeout.

Implementing Custom setTimeout

Here’s an implementation of a custom setTimeout function:

function customSetTimeout(callback, delay) {
  const start = Date.now();
  let timeoutId = null;
  
  function checkTime() {
    const current = Date.now();
    if (current - start >= delay) {
      callback();
    } else {
      timeoutId = requestAnimationFrame(checkTime);
    }
  }
  
  timeoutId = requestAnimationFrame(checkTime);
  
  return {
    clear: () => cancelAnimationFrame(timeoutId),
  };
}
Explanation:
  • Tracking Start Time: Store the start time using Date.now().
  • Check Time Function: Use requestAnimationFrame to repeatedly check if the specified delay has elapsed.
  • Callback Execution: Execute the callback function once the delay has passed.
  • Return Object: Return an object with a clear method to cancel the timeout.

Practical Examples

Consider examples with different delays and callbacks:

const timeout1 = customSetTimeout(() => {
  console.log('Timeout 1 executed after 1000ms');
}, 1000);
 
const timeout2 = customSetTimeout(() => {
  console.log('Timeout 2 executed after 2000ms');
}, 2000);
 
// Cancel the second timeout before it executes
setTimeout(() => {
  timeout2.clear();
  console.log('Timeout 2 cancelled');
}, 1500);

Handling Edge Cases

  1. Immediate Execution: Handle cases where the delay is zero or negative.
  2. Cancel Timeout: Provide a method to cancel the timeout before it executes.

Enhanced Implementation with Immediate Execution Handling

function customSetTimeout(callback, delay) {
  if (delay <= 0) {
    callback();
    return { clear: () => {} };
  }
  
  const start = Date.now();
  let timeoutId = null;
  
  function checkTime() {
    const current = Date.now();
    if (current - start >= delay) {
      callback();
    } else {
      timeoutId = requestAnimationFrame(checkTime);
    }
  }
  
  timeoutId = requestAnimationFrame(checkTime);
  
  return {
    clear: () => cancelAnimationFrame(timeoutId),
  };
}
 
// Example usage with edge cases
const timeout3 = customSetTimeout(() => {
  console.log('Timeout 3 executed immediately');
}, 0);
 
const timeout4 = customSetTimeout(() => {
  console.log('Timeout 4 should not execute');
}, 1000);
 
timeout4.clear();

Use Cases for Custom setTimeout

  1. Learning: Understanding how asynchronous operations and event loops work in JavaScript.
  2. Polyfills: Creating a polyfill for environments where setTimeout is not available.
  3. Advanced Control: Providing advanced control over timeout functionality in specific scenarios.