|
| 1 | +/* |
| 2 | +Given a function fn, an array of arguments args, and a timeout t in milliseconds, return a cancel function cancelFn. |
| 3 | +
|
| 4 | +After a delay of t, fn should be called with args passed as parameters unless cancelFn was invoked before the delay of t milliseconds elapses, specifically at cancelT ms. In that case, fn should never be called. |
| 5 | +
|
| 6 | + |
| 7 | +
|
| 8 | +Example 1: |
| 9 | +
|
| 10 | +Input: fn = (x) => x * 5, args = [2], t = 20, cancelT = 50 |
| 11 | +Output: [{"time": 20, "returned": 10}] |
| 12 | +Explanation: |
| 13 | +const result = [] |
| 14 | +
|
| 15 | +const fn = (x) => x * 5 |
| 16 | +
|
| 17 | +const start = performance.now() |
| 18 | +
|
| 19 | +const log = (...argsArr) => { |
| 20 | + const diff = Math.floor(performance.now() - start); |
| 21 | + result.push({"time": diff, "returned": fn(...argsArr)}) |
| 22 | +} |
| 23 | + |
| 24 | +const cancel = cancellable(log, [2], 20); |
| 25 | +
|
| 26 | +const maxT = Math.max(t, 50) |
| 27 | + |
| 28 | +setTimeout(cancel, cancelT) |
| 29 | +
|
| 30 | +setTimeout(() => { |
| 31 | + console.log(result) // [{"time":20,"returned":10}] |
| 32 | +}, 65) |
| 33 | +
|
| 34 | +The cancellation was scheduled to occur after a delay of cancelT (50ms), which happened after the execution of fn(2) at 20ms. |
| 35 | +Example 2: |
| 36 | +
|
| 37 | +Input: fn = (x) => x**2, args = [2], t = 100, cancelT = 50 |
| 38 | +Output: [] |
| 39 | +Explanation: The cancellation was scheduled to occur after a delay of cancelT (50ms), which happened before the execution of fn(2) at 100ms, resulting in fn(2) never being called. |
| 40 | +Example 3: |
| 41 | +
|
| 42 | +Input: fn = (x1, x2) => x1 * x2, args = [2,4], t = 30, cancelT = 100 |
| 43 | +Output: [{"time": 30, "returned": 8}] |
| 44 | +Explanation: The cancellation was scheduled to occur after a delay of cancelT (100ms), which happened after the execution of fn(2,4) at 30ms. |
| 45 | + |
| 46 | +
|
| 47 | +Constraints: |
| 48 | +
|
| 49 | +fn is a function |
| 50 | +args is a valid JSON array |
| 51 | +1 <= args.length <= 10 |
| 52 | +20 <= t <= 1000 |
| 53 | +10 <= cancelT <= 1000 |
| 54 | +*/ |
| 55 | + |
| 56 | +/** |
| 57 | + * @param {Function} fn |
| 58 | + * @param {Array} args |
| 59 | + * @param {number} t |
| 60 | + * @return {Function} |
| 61 | + */ |
| 62 | +const args = [2], |
| 63 | + t = 20, |
| 64 | + cancelT = 50; |
| 65 | +const fn = (x) => x * 5; |
| 66 | +const result = []; |
| 67 | + |
| 68 | +// Create a cancellable timeout |
| 69 | +var cancellable = function (fn, args, t) { |
| 70 | + // Define a cancel function that will clear the timeout |
| 71 | + const cancelFn = () => clearTimeout(idTimeout); |
| 72 | + |
| 73 | + // Set up a timeout to execute the function after the specified delay |
| 74 | + const idTimeout = setTimeout(() => fn(...args), t); |
| 75 | + |
| 76 | + // When/if we call the function, it will return cancelFn, |
| 77 | + // and since the return line calls (and consequentially executes) |
| 78 | + // cancelFn, timeout will be cancelled, thereby cancelling fn execution. |
| 79 | + return cancelFn; |
| 80 | +}; |
| 81 | + |
| 82 | +console.log(cancellable(fn, args, t)); |
0 commit comments