Given a function fn, an array of arguments args, and a timeout t in milliseconds, return a cancel function cancelFn.
After a delay of cancelTimeMs, the returned cancel function cancelFn will be invoked.
setTimeout(cancelFn, cancelTimeMs)
Initially, the execution of the function fn should be delayed by t milliseconds.
If, before the delay of t milliseconds, the function cancelFn is invoked, it should cancel the delayed execution of fn. Otherwise, if cancelFn is not invoked within the specified delay t, fn should be executed with the provided args as arguments.
Example 1:
Input: fn = (x) => x * 5, args = [2], t = 20
Output: [{"time": 20, "returned": 10}]
Explanation:
const cancelTimeMs = 50;
const cancelFn = cancellable((x) => x * 5, [2], 20);
setTimeout(cancelFn, cancelTimeMs);
The cancellation was scheduled to occur after a delay of cancelTimeMs (50ms), which happened after the execution of fn(2) at 20ms.
Example 2:
Input: fn = (x) => x**2, args = [2], t = 100 Output: [] Explanation: const cancelTimeMs = 50; const cancelFn = cancellable((x) => x**2, [2], 100); setTimeout(cancelFn, cancelTimeMs); The cancellation was scheduled to occur after a delay of cancelTimeMs (50ms), which happened before the execution of fn(2) at 100ms, resulting in fn(2) never being called.
Example 3:
Input: fn = (x1, x2) => x1 * x2, args = [2,4], t = 30
Output: [{"time": 30, "returned": 8}]
Explanation:
const cancelTimeMs = 100;
const cancelFn = cancellable((x1, x2) => x1 * x2, [2,4], 30);
setTimeout(cancelFn, cancelTimeMs);
The cancellation was scheduled to occur after a delay of cancelTimeMs (100ms), which happened after the execution of fn(2,4) at 30ms.
Constraints:
fn is a functionargs is a valid JSON array1 <= args.length <= 1020 <= t <= 100010 <= cancelTimeMs <= 1000Problem Overview: You need to schedule a function fn to run after t milliseconds and return another function that cancels the scheduled execution. If the cancel function runs before the timer fires, fn must never execute. This problem checks your understanding of timer APIs and basic asynchronous programming.
Approach 1: Using setTimeout and clearTimeout (O(1) time, O(1) space)
The direct solution schedules the callback using setTimeout and stores the returned timer identifier. JavaScript timers return an ID that uniquely represents the scheduled task. The cancellation function simply calls clearTimeout(timerId), which removes the scheduled callback from the event loop queue before it executes.
The key insight is that timer scheduling and cancellation are constant‑time operations managed by the runtime. No iteration or extra data structures are required. When the cancel function executes before the delay expires, the timer is invalidated and the callback never runs. If the timer already fired, calling clearTimeout has no effect.
This approach mirrors how real systems manage scheduled tasks. Most interviewers expect you to know the relationship between setTimeout and clearTimeout and how the event loop handles deferred execution in JavaScript.
Approach 2: Using Promises for Asynchronous Control (O(1) time, O(1) space)
Another implementation wraps the delayed execution inside a Promise. A timer triggers the promise resolution after t milliseconds, which then executes the callback. The cancellation function prevents the resolution by clearing the timer or toggling a flag that stops the callback from running.
This design is useful when your codebase already relies heavily on promises or async workflows. For example, a promise-based wrapper can integrate with async/await, cancellation tokens, or higher-level task management systems. The runtime cost remains constant because only one timer and one promise object are created.
While slightly more abstract, this version demonstrates how timers can coordinate with Promises to control asynchronous flow. The core mechanism still relies on canceling the scheduled timeout before execution.
Recommended for interviews: The setTimeout + clearTimeout approach is the expected solution. It shows you understand how timers work in the event loop and how scheduled callbacks can be canceled. The promise-based version is useful for system design discussions or async-heavy applications, but the direct timer cancellation approach is clearer and closer to how the runtime APIs are designed.
This approach leverages JavaScript's built-in setTimeout and clearTimeout functions. We schedule a timeout to execute the function fn after t milliseconds, and we return a cancelFn that, when called, cancels this scheduled timeout.
C does not have direct support for asynchronous delay management similar to setTimeout in JavaScript, particularly in standard libraries. Such functionality generally requires external libraries or platform-specific code for thread and timer management.
In C, without a standard set of functions for asynchronous timeouts, it's less about algorithmic complexity and more about the overhead of managing threads, which varies based on the implementation details.
This alternative approach involves using Promises to manage asynchronous execution and potential cancelation. By wrapping the setTimeout within a Promise, we can have more control over its execution and cancelation by managing the Promise lifecycle.
Similar to the first approach, C would require a significant amount of helper code to achieve a Promise-like system, often using threads and synchronization primitives, unavailable directly in the standard library.
Time Complexity and space complexity would depend on the specific threading mechanism and the use of synchronization primitives.
TypeScript
JavaScript
| Approach | Complexity |
|---|---|
| Using setTimeout and clearTimeout | In C, without a standard set of functions for asynchronous timeouts, it's less about algorithmic complexity and more about the overhead of managing threads, which varies based on the implementation details. |
| Using Promises for Asynchronous Control | Time Complexity and space complexity would depend on the specific threading mechanism and the use of synchronization primitives. |
| Default Approach | — |
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Using setTimeout and clearTimeout | O(1) | O(1) | Standard solution when working directly with timers or event loop scheduling |
| Using Promises for Asynchronous Control | O(1) | O(1) | When integrating timer logic into promise-based or async/await workflows |
Timeout Cancellation | Leetcode 2715 | Promises and Time | 30 Days of JavaScript #javascript • Learn With Chirag • 3,631 views views
Watch 9 more video solutions →Practice Timeout Cancellation with our built-in code editor and test cases.
Practice on FleetCode