Skip to main content

Interval Cancellation - Solution & Explanation

Easy6 min read
Practice this problem

Problem Statement

Given a function fn, an array of arguments args, and an interval time t, return a cancel function cancelFn.

After a delay of cancelTimeMs, the returned cancel function cancelFn will be invoked.

setTimeout(cancelFn, cancelTimeMs)

The function fn should be called with args immediately and then called again every t milliseconds until cancelFn is called at cancelTimeMs ms.

 

Example 1:

Input: fn = (x) => x * 2, args = [4], t = 35
Output: 
[
   {"time": 0, "returned": 8},
   {"time": 35, "returned": 8},
   {"time": 70, "returned": 8},
   {"time": 105, "returned": 8},
   {"time": 140, "returned": 8},
   {"time": 175, "returned": 8}
]
Explanation: 
const cancelTimeMs = 190;
const cancelFn = cancellable((x) => x * 2, [4], 35);
setTimeout(cancelFn, cancelTimeMs);

Every 35ms, fn(4) is called. Until t=190ms, then it is cancelled.
1st fn call is at 0ms. fn(4) returns 8.
2nd fn call is at 35ms. fn(4) returns 8.
3rd fn call is at 70ms. fn(4) returns 8.
4th fn call is at 105ms. fn(4) returns 8.
5th fn call is at 140ms. fn(4) returns 8.
6th fn call is at 175ms. fn(4) returns 8.
Cancelled at 190ms

Example 2:

Input: fn = (x1, x2) => (x1 * x2), args = [2, 5], t = 30
Output: 
[
   {"time": 0, "returned": 10},
   {"time": 30, "returned": 10},
   {"time": 60, "returned": 10},
   {"time": 90, "returned": 10},
   {"time": 120, "returned": 10},
   {"time": 150, "returned": 10}
]
Explanation: 
const cancelTimeMs = 165; 
const cancelFn = cancellable((x1, x2) => (x1 * x2), [2, 5], 30) 
setTimeout(cancelFn, cancelTimeMs)

Every 30ms, fn(2, 5) is called. Until t=165ms, then it is cancelled.
1st fn call is at 0ms 
2nd fn call is at 30ms 
3rd fn call is at 60ms 
4th fn call is at 90ms 
5th fn call is at 120ms 
6th fn call is at 150ms
Cancelled at 165ms

Example 3:

Input: fn = (x1, x2, x3) => (x1 + x2 + x3), args = [5, 1, 3], t = 50
Output: 
[
   {"time": 0, "returned": 9},
   {"time": 50, "returned": 9},
   {"time": 100, "returned": 9},
   {"time": 150, "returned": 9}
]
Explanation: 
const cancelTimeMs = 180;
const cancelFn = cancellable((x1, x2, x3) => (x1 + x2 + x3), [5, 1, 3], 50)
setTimeout(cancelFn, cancelTimeMs)

Every 50ms, fn(5, 1, 3) is called. Until t=180ms, then it is cancelled. 
1st fn call is at 0ms
2nd fn call is at 50ms
3rd fn call is at 100ms
4th fn call is at 150ms
Cancelled at 180ms

 

Constraints:

  • fn is a function
  • args is a valid JSON array
  • 1 <= args.length <= 10
  • 30 <= t <= 100
  • 10 <= cancelTimeMs <= 500

Approach Overview

Problem Overview: You need to implement a utility that repeatedly executes a function at fixed time intervals and returns a cancellation function. The function runs immediately, then continues running every t milliseconds until the returned cancel function stops the interval.

Approach 1: Using setInterval and clearInterval (O(1) time, O(1) space)

This approach relies directly on JavaScript’s built-in timer APIs. First, call fn(...args) immediately to satisfy the requirement that the function runs at time 0. Then create a repeating timer with setInterval that invokes the same function every t milliseconds. Store the interval ID returned by setInterval. The cancel function simply calls clearInterval(intervalId), which stops all future executions.

The key insight is that setInterval already handles repeated scheduling internally, so you only manage the initial call and the cancellation handle. This keeps the implementation minimal and avoids manual timer management. Setup cost is constant because you create a single interval and return a closure referencing its ID. This is the most idiomatic solution when working with JavaScript timer APIs.

Approach 2: Manual Loop with setTimeout (O(1) time, O(1) space)

This approach simulates interval behavior using repeated setTimeout calls. Start by executing fn(...args) immediately. Then define a helper function that schedules the next execution with setTimeout. Each time the timeout fires, it runs the function and schedules another timeout.

To support cancellation, track a boolean flag or the timeout ID. When the cancel function runs, update the flag or call clearTimeout to prevent the next scheduled execution. This technique is common in asynchronous programming when you need finer control over scheduling behavior compared to setInterval. It also avoids overlapping executions if a task takes longer than the interval.

The recursive scheduling pattern is slightly more verbose but flexible. Developers often prefer it when precise timing control or dynamic delays are required.

Recommended for interviews: The setInterval and clearInterval solution is the expected answer. It shows you understand how browser and Node.js timer functions work and how closures retain the interval ID for cancellation. The manual setTimeout loop demonstrates deeper understanding of scheduling mechanics and event-loop behavior, which can be useful if interviewers ask about alternative implementations.

Approach 1: Approach 1: Using setInterval and clearInterval

This approach leverages JavaScript's setInterval function to repeatedly invoke a function at specified intervals. The function is initially called immediately, then periodically every t milliseconds. A separate cancellation function is prepared using clearInterval to stop the repeated invocation when it's called after cancelTimeMs.

This implementation of the cancel function sets up an interval using setInterval. Initially, the function fn is called with the provided args. Then, every t milliseconds, the setInterval calls the function again. The clearInterval function is returned to stop further executions when called.

Code

JavaScript

Complexity

Time Complexity: O(1) per function call, ignoring the delay.
Space Complexity: O(1) as no additional data structures are used.

Try this approach in the editor →

Approach 2: Approach 2: Manual Loop with setTimeout

This approach uses recursive calls to setTimeout to simulate the behavior of setInterval. This gives finer control over each invocation of the function, and you can easily stop future calls by not setting further timeouts.

This code sets up a manual loop using setTimeout. The helper function callFn checks if the process is still active, invokes the function, and schedules the next invocation with setTimeout. The returned cancelFn sets the flag isActive to false, stopping further invocations.

Code

JavaScript

Complexity

Time Complexity: O(1) per function call, ignoring the delay.
Space Complexity: O(1) as only a boolean flag is used to manage state.

Try this approach in the editor →

Approach 3: Default Approach

Code

TypeScript

Try this approach in the editor →

Complexity Comparison

ApproachComplexity
Approach 1: Using setInterval and clearInterval

Time Complexity: O(1) per function call, ignoring the delay.
Space Complexity: O(1) as no additional data structures are used.

Approach 2: Manual Loop with setTimeout

Time Complexity: O(1) per function call, ignoring the delay.
Space Complexity: O(1) as only a boolean flag is used to manage state.

Default Approach—

Detailed Complexity Analysis

ApproachTimeSpaceWhen to Use
Using setInterval and clearIntervalO(1) setupO(1)Best general solution when implementing repeating timers in JavaScript
Manual Loop with setTimeoutO(1) setupO(1)Useful when you need finer control over scheduling or want to avoid overlapping executions

Video Solution

Interval Cancellation | Leetcode 2725 | Promises and Time | 30 Days of JavaScript #javascript • Learn With Chirag • 2,570 views views

Watch 9 more video solutions →

Frequently Asked Questions

Is Interval Cancellation easy or hard?
Interval Cancellation is categorized as an Easy problem. The core challenge is understanding how JavaScript timers work and returning a closure that cancels the scheduled execution. Developers familiar with setInterval and clearInterval usually solve it quickly.
Interval Cancellation Python/Java solution
This problem is designed specifically for JavaScript because it relies on browser or Node.js timer APIs like setInterval and setTimeout. Languages such as Python or Java would implement similar behavior using threading timers or scheduled executors rather than built-in interval functions.
How to solve Interval Cancellation in O(1)?
Execute the target function immediately, then create a repeating timer using setInterval with delay t. Store the interval ID returned by setInterval and return a function that calls clearInterval with that ID. The entire setup takes constant time and memory.
What is the best approach for Interval Cancellation?
The most practical approach uses JavaScript's setInterval to schedule repeated execution and clearInterval to stop it. Call the function once immediately, store the interval ID, and return a cancel function that clears the interval. This solution has O(1) setup time and O(1) space and directly leverages built-in timer APIs.
Is Interval Cancellation asked at Google/Amazon/Meta?
Interval Cancellation is more common in JavaScript-focused interview rounds or frontend engineering screens. Companies evaluating async JavaScript knowledge may ask similar timer or event-loop problems to test understanding of closures, scheduling, and cancellation patterns.
What data structure is used in Interval Cancellation?
No traditional data structure is required. The solution mainly uses JavaScript timer APIs such as setInterval, setTimeout, clearInterval, and clearTimeout. A closure is used to retain access to the timer ID so the cancel function can stop future executions.
What is the time complexity of Interval Cancellation?
The setup complexity is O(1) because the solution only performs a constant number of operations: executing the function once and creating a single interval or timeout. Space complexity is also O(1) since only the timer ID or a small closure reference is stored.

Ready to solve this problem?

Practice Interval Cancellation with our built-in code editor and test cases.

Practice on FleetCode