2715. Timeout Cancellation
IntuitionThe goal is to execute a function fn with the given arguments args after a delay of t milliseconds.
However, we also need a way to cancel the execution
# Intuition
<!-- Describe your first thoughts on how to solve this problem. -->
The goal is to execute a function `fn` with the given arguments `args` after a delay of `t` milliseconds.  
However, we also need a way to cancel the execution if needed before `t` milliseconds elapse.  

- We can schedule the execution using `setTimeout()`.  
- To allow cancellation, we store the timeout ID and use `clearTimeout()` to stop execution if the cancel function is called before the timeout completes.  


# Approach
<!-- Describe your approach to solving the problem. -->
1. **Define the cancellable function**  
   - It takes `fn`, `args`, and `t` as input.  
   - `setTimeout()` is used to delay the function execution.  

2. **Schedule function execution**  
   - Call `fn(...args)` inside a `setTimeout()` after `t` milliseconds.  
   - Store the timeout ID in a variable (`timer`).  

3. **Provide a cancellation mechanism**  
   - Define a `cancel` function that calls `clearTimeout(timer)`.  
   - Return `cancel` so it can be used later to prevent execution.  

4. **Example Flow**  
   - The function is scheduled to execute after `t` milliseconds.  
   - If `cancel()` is called before `t`, execution is prevented.  
   - Otherwise, `fn(...args)` executes normally.  


# Complexity
- Time complexity:
<!-- Add your time complexity here, e.g. $$O(n)$$ -->
- **Best Case (Cancellation Before Execution)**  
  - `setTimeout()` → `O(1)`  
  - `clearTimeout()` → `O(1)`  
  - **Total: O(1)**  

- **Worst Case (Execution Happens)**  
  - `setTimeout()` → `O(1)`  
  - `fn(...args)` executes in its own complexity (assume `O(1)`).  
  - **Total: O(1)**  

Thus, the overall **time complexity is O(1)**.  

- Space complexity:
<!-- Add your space complexity here, e.g. $$O(n)$$ -->
- We store only one variable (`timer`) → **O(1)**.  
- The function does not use additional space.  
- `setTimeout()` holds a function reference in memory, but this is a constant overhead. 

# Code
```javascript []
/**
 * @param {Function} fn
 * @param {Array} args
 * @param {number} t
 * @return {Function}
 */
var cancellable = function(fn, args, t) {
    // return function ()

    const cancel = () => {
        clearTimeout(timer);
    }

    const timer = setTimeout(() => {
        fn(...args);
    }, t);

    return cancel;

    
};

/**
 *  const result = [];
 *
 *  const fn = (x) => x * 5;
 *  const args = [2], t = 20, cancelTimeMs = 50;
 *
 *  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);
 *
 *  const maxT = Math.max(t, cancelTimeMs);
 *           
 *  setTimeout(cancel, cancelTimeMs);
 *
 *  setTimeout(() => {
 *      console.log(result); // [{"time":20,"returned":10}]
 *  }, maxT + 15)
 */
```
['JavaScript']