2725. 间隔取消
2725. 间隔取消
题目
Given a function fn
, an array of arguments args
, and an interval time t
, return a cancel function cancelFn
.
After a delay of cancelTimeMs
, the returned cancel function cancelFn
will be invoked.
setTimeout(cancelFn, cancelTimeMs)
The function fn
should be called with args
immediately and then called again every t
milliseconds until cancelFn
is called at cancelTimeMs
ms.
Example 1:
Input: fn = (x) => x * 2, args = [4], t = 35
Output:
[
{"time": 0, "returned": 8},
{"time": 35, "returned": 8},
{"time": 70, "returned": 8},
{"time": 105, "returned": 8},
{"time": 140, "returned": 8},
]
Explanation:
const cancelTimeMs = 190;
const cancelFn = cancellable((x) => x * 2, [4], 35);
setTimeout(cancelFn, cancelTimeMs);
Every 35ms, fn(4) is called. Until t=190ms, then it is cancelled.
1st fn call is at 0ms. fn(4) returns 8.
2nd fn call is at 35ms. fn(4) returns 8.
3rd fn call is at 70ms. fn(4) returns 8.
4th fn call is at 105ms. fn(4) returns 8.
5th fn call is at 140ms. fn(4) returns 8.
6th fn call is at 175ms. fn(4) returns 8.
Cancelled at 190ms
Example 2:
Input: fn = (x1, x2) => (x1 * x2), args = [2, 5], t = 30
Output:
[
{"time": 0, "returned": 10},
{"time": 30, "returned": 10},
{"time": 60, "returned": 10},
{"time": 90, "returned": 10},
{"time": 120, "returned": 10},
]
Explanation:
const cancelTimeMs = 165;
const cancelFn = cancellable((x1, x2) => (x1 * x2), [2, 5], 30)
setTimeout(cancelFn, cancelTimeMs)
Every 30ms, fn(2, 5) is called. Until t=165ms, then it is cancelled.
1st fn call is at 0ms
2nd fn call is at 30ms
3rd fn call is at 60ms
4th fn call is at 90ms
5th fn call is at 120ms
6th fn call is at 150ms
Cancelled at 165ms
Example 3:
Input: fn = (x1, x2, x3) => (x1 + x2 + x3), args = [5, 1, 3], t = 50
Output:
[
{"time": 0, "returned": 9},
{"time": 50, "returned": 9},
{"time": 100, "returned": 9},
]
Explanation:
const cancelTimeMs = 180;
const cancelFn = cancellable((x1, x2, x3) => (x1 + x2 + x3), [5, 1, 3], 50)
setTimeout(cancelFn, cancelTimeMs)
Every 50ms, fn(5, 1, 3) is called. Until t=180ms, then it is cancelled.
1st fn call is at 0ms
2nd fn call is at 50ms
3rd fn call is at 100ms
4th fn call is at 150ms
Cancelled at 180ms
Constraints:
fn
is a functionargs
is a valid JSON array1 <= args.length <= 10
30 <= t <= 100
10 <= cancelTimeMs <= 500
题目大意
现给定一个函数 fn
,一个参数数组 args
和一个时间间隔 t
,返回一个取消函数 cancelFn
。
在经过 cancelTimeMs
毫秒的延迟后,将调用返回的取消函数 cancelFn
。
setTimeout(cancelFn, cancelTimeMs)
函数 fn
应立即使用参数 args
调用,然后每隔 t
毫秒调用一次,直到在 cancelTimeMs
毫秒时调用 cancelFn
。
提示:
fn
是一个函数args
是一个有效的 JSON 数组1 <= args.length <= 10
30 <= t <= 100
10 <= cancelT <= 500
解题思路
- 题目要求函数
fn
应立即使用参数args
调用,然后每隔t
毫秒调用一次,所以立即手动执行fn
一次。 - 使用
setInterval
来启动定时器,每隔delay
毫秒会执行一次传入的函数fn
,第一次执行发生在delay
毫秒之后。 setInterval
返回一个intervalId
,这是唯一标识这个定时器的值,可以通过调用clearInterval(intervalId)
来取消定时器。- 返回取消函数,这个取消函数在被调用时,会停止定时器的继续执行。
复杂度分析
- 时间复杂度:
O(1)
,因为setInterval
和clearInterval
都是常数时间操作。 - 空间复杂度:
O(1)
,只存储了intervalId
作为唯一的定时器标识。
代码
/**
* @param {Function} fn
* @param {Array} args
* @param {number} t
* @return {Function}
*/
var cancellable = function (fn, args, t) {
// 立即调用一次 fn
fn(...args);
// 使用 setInterval 启动定时器,每隔 t 毫秒执行一次 fn
const intervalId = setInterval(() => fn(...args), t);
// 返回一个取消函数,可以通过调用该函数来清除定时器
const cancelFn = () => clearInterval(intervalId);
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)
*/