2725. Leetcode Interval Cancellation Solution
IntuitionThis problem requires implementing a function that repeatedly calls another function at a fixed time interval and provides a way to cancel it when need
# **Intuition**

This problem requires implementing a function that **repeatedly calls another function at a fixed time interval** and provides a way to cancel it when needed. We can achieve this using JavaScript’s **`setInterval()`** along with **`clearInterval()`** for cancellation.

The key idea is to:

1. **Call the function immediately** when `cancellable` is invoked.
2. **Use `setInterval()`** to call the function repeatedly at the given interval.
3. **Return a cancel function** that stops the interval execution when invoked.

---

# **Understanding setInterval() & clearInterval()**

✅ **What is `setInterval()`?**  
`setInterval()` repeatedly executes a function **after a fixed delay** (in milliseconds).

🔹 **Syntax:**
```js
let intervalId = setInterval(callback, delay);
```
- `callback` → The function to be executed repeatedly.
- `delay` → Time in milliseconds between executions.

✅ **What is `clearInterval()`?**  
`clearInterval(intervalId)` stops the execution of a repeating `setInterval()`.

🔹 **Example:**
```js
let intervalId = setInterval(() => console.log("Running"), 1000);
setTimeout(() => clearInterval(intervalId), 5000); // Stops after 5 sec
```

---

# **Approach**

I explored **two different approaches** to implement interval cancellation.

---

## 🔹 **Approach 1: Basic Implementation with `setInterval()`**
```js
var cancellable = function(fn, args, t) {
    fn(...args);
    let interval = setInterval(() => fn(...args), t);
    return () => clearInterval(interval);
};
```
📌 **Explanation:**
- The function is executed **immediately** using `fn(...args)`.
- `setInterval()` ensures the function is repeatedly executed after every `t` milliseconds.
- The function **returns a cancel function**, which calls `clearInterval(interval)` to stop execution.

✅ **Pros:**
- Simple and effective.
- Uses minimal code.

---

## 🔹 **Approach 2: Using an Explicit Cancel Function**
```js
/**
 * @param {Function} fn
 * @param {Array} args
 * @param {number} t
 * @return {Function}
 */
var cancellable = function(fn, args, t) {
    fn(...args);
    let interval = setInterval(() => {
        fn(...args);
    }, t);

    let cancelFn = () => {
        clearInterval(interval);
    }

    return cancelFn;
};
```
📌 **Differences from Approach 1:**
- **Explicitly defines** `cancelFn`, making it more readable.
- Adds **better structure** for future modifications.
- The behavior remains the same, but this structure is **easier to extend**.

✅ **Pros:**
- Cleaner code with a well-defined cancel function.
- Easier to modify and debug.

---

# **Complexity Analysis**
| Operation | Time Complexity | Space Complexity |
|-----------|----------------|------------------|
| Calling the function | O(1) | O(1) |
| setInterval execution | O(n) (for `n` calls) | O(1) |
| Cancelling the interval | O(1) | O(1) |

🔹 **Overall Complexity:**  
- **Time Complexity:** `O(n)`, where `n` is the number of times `fn` executes before cancellation.  
- **Space Complexity:** `O(1)`, as we only store a reference to the interval.

---

![image.png](https://assets.leetcode.com/users/images/81bd4fea-86ab-4e4b-8041-3edba25572b0_1743237836.9447615.png)


---

# **Code Implementation**
```js
/**
 * @param {Function} fn
 * @param {Array} args
 * @param {number} t
 * @return {Function}
 */
var cancellable = function(fn, args, t) {
    fn(...args);
    let interval = setInterval(() => {
        fn(...args);
    }, t);

    let cancelFn = () => {
        clearInterval(interval);
    }

    return cancelFn;
};

/**
 *  const result = [];
 *
 *  const fn = (x) => x * 2;
 *  const args = [4], t = 35, cancelTimeMs = 190;
 *
 *  const start = performance.now();
 *
 *  const log = (...argsArr) => {
 *      const diff = Math.floor(performance.now() - start);
 *      result.push({"time": diff, "returned": fn(...argsArr)});
 *  }
 *       
 *  const cancel = cancellable(log, args, t);
 *
 *  setTimeout(cancel, cancelTimeMs);
 *   
 *  setTimeout(() => {
 *      console.log(result); // [
 *                           //     {"time":0,"returned":8},
 *                           //     {"time":35,"returned":8},
 *                           //     {"time":70,"returned":8},
 *                           //     {"time":105,"returned":8},
 *                           //     {"time":140,"returned":8},
 *                           //     {"time":175,"returned":8}
 *                           // ]
 *  }, cancelTimeMs + t + 15)    
 */
```

---

# **Important Topics to Learn 📚**
✅ `setInterval()` and `clearInterval()`  
✅ Understanding **asynchronous execution** in JavaScript  
✅ **Callback functions** and how to manage repeating tasks  
✅ How to **return functions from functions** for better modularity  

---

# 🚀 **Support & Feedback**
✅ If you found this helpful, **please upvote & comment** on my solution!  
💬 Let’s discuss alternative solutions & improvements! 🚀
['JavaScript']