# Timeout Cancellation (LeetCode #2715)
IntuitionThe problem requires us to execute a function with a delay and allow its execution to be canceled before the timeout expires. If the cancellation occur
# Intuition
The problem requires us to execute a function with a delay and allow its execution to be canceled before the timeout expires. If the cancellation occurs before the timeout, the function should not be executed. The challenge is to handle both the function execution and the cancellation mechanism efficiently while ensuring the correct time is captured when the function is invoked.

# Approach
The approach to solving this problem revolves around using JavaScript's `setTimeout` to handle the delayed execution of the function and `clearTimeout` for cancellation. The `cancellable` function receives a function `fn`, arguments `args`, and a timeout `t`. It sets up a timeout to invoke the function after `t` milliseconds and returns a cancellation function to clear the timeout if invoked before the function is executed.

## Steps:
1. **Setting a Timeout**: Use `setTimeout` to invoke the provided function `fn` with the given arguments `args` after a delay of `t` milliseconds.
2. **Cancellation**: The `cancellable` function returns a `cancelFn` which, when invoked, calls `clearTimeout` to prevent the function from executing if canceled before the timeout.
3. **Time Logging**: Track the time at which the function is executed using `performance.now()`, and log the time of execution and the result.

# Complexity

## Time Complexity:
- The time complexity is **O(1)** because:
  - We are only setting a timeout (`setTimeout`) and performing a single function call when the timeout completes. 
  - The cancellation operation (`clearTimeout`) is also constant time.

## Space Complexity:
- The space complexity is **O(1)** because we only store a few variables (`timeoutId`, `startTime`, etc.), and no additional data structures are used that grow with input size.

# Code
```javascript []
/**
 * @param {Function} fn
 * @param {Array} args
 * @param {number} t
 * @return {Function}
 */
var cancellable = function(fn, args, t) {
    let timeoutId;
    
    // Create a function to cancel the timeout
    const cancelFn = () => clearTimeout(timeoutId);
    
    // Set a timeout to invoke the function after t milliseconds
    timeoutId = setTimeout(() => {
        fn(...args); // Call the function with the provided arguments
    }, t);

    return cancelFn; // Return the cancel function to stop the timeout if needed
};

/**
 *  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']