跳至主要內容

2715. 执行可取消的延迟函数


2715. 执行可取消的延迟函数open in new window

🟢   🔗 力扣open in new window LeetCodeopen in new window

题目

Given a function fn, an array of arguments args, and a timeout t in milliseconds, return a cancel function cancelFn.

After a delay of cancelTimeMs, the returned cancel function cancelFn will be invoked.

setTimeout(cancelFn, cancelTimeMs)

Initially, the execution of the function fn should be delayed by t milliseconds.

If, before the delay of t milliseconds, the function cancelFn is invoked, it should cancel the delayed execution of fn. Otherwise, if cancelFn is not invoked within the specified delay t, fn should be executed with the provided args as arguments.

Example 1:

Input: fn = (x) => x * 5, args = [2], t = 20

Output: [{"time": 20, "returned": 10}]

Explanation:

const cancelTimeMs = 50;

const cancelFn = cancellable((x) => x * 5, [2], 20);

setTimeout(cancelFn, cancelTimeMs);

The cancellation was scheduled to occur after a delay of cancelTimeMs (50ms), which happened after the execution of fn(2) at 20ms.

Example 2:

Input: fn = (x) => x**2, args = [2], t = 100

Output: []

Explanation:

const cancelTimeMs = 50;

const cancelFn = cancellable((x) => x**2, [2], 100);

setTimeout(cancelFn, cancelTimeMs);

The cancellation was scheduled to occur after a delay of cancelTimeMs (50ms), which happened before the execution of fn(2) at 100ms, resulting in fn(2) never being called.

Example 3:

Input: fn = (x1, x2) => x1 * x2, args = [2,4], t = 30

Output: [{"time": 30, "returned": 8}]

Explanation: const cancelTimeMs = 100;

const cancelFn = cancellable((x1, x2) => x1 * x2, [2,4], 30);

setTimeout(cancelFn, cancelTimeMs);

The cancellation was scheduled to occur after a delay of cancelTimeMs (100ms), which happened after the execution of fn(2,4) at 30ms.

Constraints:

  • fn is a function
  • args is a valid JSON array
  • 1 <= args.length <= 10
  • 20 <= t <= 1000
  • 10 <= cancelTimeMs <= 1000

题目大意

给定一个函数 fn ,一个参数数组 args 和一个以毫秒为单位的超时时间 t ,返回一个取消函数 cancelFn

cancelTimeMs 的延迟后,返回的取消函数 cancelFn 将被调用。

setTimeout(cancelFn, cancelTimeMs)

最初,函数 fn 的执行应该延迟 t 毫秒。

如果在 t 毫秒的延迟之前调用了函数 cancelFn,它应该取消 fn 的延迟执行。否则,如果在指定的延迟 t 内没有调用 cancelFn,则应执行 fn,并使用提供的 args 作为参数。

提示:

  • fn 是一个函数
  • args 是一个有效的 JSON 数组
  • 1 <= args.length <= 10
  • 20 <= t <= 1000
  • 10 <= cancelTimeMs <= 1000

解题思路

  1. 创建定时器:使用 setTimeout 来执行 fn,并设置延迟 t 毫秒后执行。

  2. 实现取消功能setTimeout 会返回一个 timer 句柄,可以通过 clearTimeout(timer) 来取消该定时器。返回一个取消函数 cancelFn,该函数被调用时会清除定时器,阻止 fn 的执行。

复杂度分析

  • 时间复杂度O(1)setTimeoutclearTimeout 的调用都是常数时间操作。
  • 空间复杂度O(1),存储一个定时器句柄 timer 以及取消函数占用常数空间。

代码

/**
 * @param {Function} fn
 * @param {Array} args
 * @param {number} t
 * @return {Function}
 */
var cancellable = function (fn, args, t) {
	const timer = setTimeout(() => fn(...args), t); // 延迟 t 毫秒后执行 fn
	const cancelFn = () => clearTimeout(timer); // 返回取消函数
	return cancelFn;
};

/**
 *  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)
 */