Custom Interval

Updated on 16 May, 2025
Custom Interval header image

Problem Statement

The customInterval function is designed to execute another function, fn, repeatedly at intervals. These intervals are not constant but increase linearly based on the formula: delay + period * count. Here, count starts from zero and increments by one each time fn is executed. The function returns an identifier id, which can be used with another function, customClearInterval, to stop the scheduled execution.

The customClearInterval function takes this id and halts the ongoing execution pattern set by customInterval. This mechanism allows for dynamic control over function execution timing, governed by the initial delay and a repetitive increase by the period length.

The functionalities mimic a more flexible version of JavaScript's setTimeout and setInterval, which in some environments like Node.js would return an object instead of a number—adjusting for simplicity, customInterval instead returns a numerical id.

Examples

Example 1

Input:

delay = 50, period = 20, cancelTime = 225

Output:

[50,120,210]

Explanation:

const t = performance.now()  
const result = []
        
const fn = () => {
result.push(Math.floor(performance.now() - t))
}
const id = customInterval(fn, delay, period)
setTimeout(() => {
customClearInterval(id)
}, 225)
50 + 20 * 0 = 50 // 50ms - 1st function call
50 + 20 * 1 = 70 // 50ms + 70ms = 120ms - 2nd function call
50 + 20 * 2 = 90 // 50ms + 70ms + 90ms = 210ms - 3rd function call

Example 2

Input:

delay = 20, period = 20, cancelTime = 150

Output:

[20,60,120]

Explanation:

20 + 20 * 0 = 20 // 20ms - 1st function call
20 + 20 * 1 = 40 // 20ms + 40ms = 60ms - 2nd function call
20 + 20 * 2 = 60 // 20ms + 40ms + 60ms = 120ms - 3rd function call

Example 3

Input:

delay = 100, period = 200, cancelTime = 500

Output:

[100,400]

Explanation:

100 + 200 * 0 = 100 // 100ms - 1st function call
100 + 200 * 1 = 300 // 100ms + 300ms = 400ms - 2nd function call

Constraints

  • 20 <= delay, period <= 250
  • 20 <= cancelTime <= 1000

Approach and Intuition

Based on the examples and constraints provided:

  1. Linearly Increasing Execution Times:

    • customInterval function initiates the execution of fn after a delay specified by the user. After the initial execution, it continues to execute fn at intervals increasing linearly by a factor of period.
    • For example, if delay is 50 ms and period is 20 ms, the function fn will first run at 50 ms, then at 70 ms (50 + 20), then at 90 ms (50 + 20 + 20), and so on.
  2. Stopping the Execution:

    • customClearInterval uses the id returned by customInterval to stop further executions of fn. This is particularly useful when one wants to stop the executions after a certain condition is met or a specific time (cancelTime) has passed.
  3. Interpretation of Output Array:

    • The output represents the actual times (relative to the start) when fn was executed. It reflects the cumulative time based on the formula used, including both the initial delay and subsequent periods.
    • Thus, for each execution time in the output, it depends on both the delay and the instances (count) of period addition before the function was halted by customClearInterval.

Through these insights, users can effectively plan and control function executions with precision timing adjustments, setting and canceling them as per the dynamics of their specific applications or use-case scenarios.

Solutions

  • JavaScript
js
const IntervalController = (() => {
   let idCount = 0;
   const mapOfIntervals = new Map();

   function startInterval(callback, initialDelay, subsequentDelay) {
      let invocationCount = 0;
      const internalId = idCount++;

      function executeInterval() {
         const timeId = setTimeout(() => {
            callback();
            executeInterval();
         }, initialDelay + subsequentDelay * invocationCount);
         invocationCount++;
         mapOfIntervals.set(internalId, timeId);
      }

      executeInterval();

      return internalId;
   }

   function stopInterval(identifier) {
      const timeId = mapOfIntervals.get(identifier);
      clearTimeout(timeId);
      mapOfIntervals.delete(identifier);
   }

   return {
      setCustomInterval: startInterval,
      clearCustomInterval: stopInterval
   };
})();

function setDynamicInterval(callbackFunction, startDelay, repeatDelay) {
   return IntervalController.setCustomInterval(callbackFunction, startDelay, repeatDelay);
}

function clearDynamicInterval(intervalId) {
   IntervalController.clearCustomInterval(intervalId);
}

The code describes a module named IntervalController that allows users to handle custom intervals in JavaScript. This module enables the initiation and termination of intervals with dynamically adjustable delays. The use of a self-invoking function ensures that the internal state, like idCount and the interval map, remains encapsulated and separate from the global scope.

  • Usage of the mapOfIntervals Map object to track active intervals:

    • Each interval is assigned a unique identifier.
    • Ensures efficient start and stop operations for individual intervals using these IDs.
  • The startInterval function:

    • Triggers a callback after an initialDelay.
    • Adjusts the delay dynamically based on the number of times the callback has been executed. It incorporates an invokeCount that multiplies with a subsequentDelay to determine the timing of subsequent executions.
    • The dynamic adjustment provides finer control over scheduling repeat callbacks as opposed to traditional constant intervals with setInterval.
  • The stopInterval function:

    • Receives an identifier for the interval to be cleared.
    • Utilizes JavaScript’s clearTimeout to stop the interval, ensuring resources are freed and execution is halted.

Use the helper functions setDynamicInterval and clearDynamicInterval to interface with the IntervalController. These enable setting custom intervals and clearing them by referring to their unique IDs. These functionalities will be particularly useful for applications that require non-linear or modified interval timing, such as in scenarios involving retry mechanisms with exponential backoff or animations that need to adjust frame delays dynamically.

Comments

No comments yet.