LeetCode 几道 Promises 和 Time 的题目

LeetCode 几道 Promises 和 Time 的题目

目的:对于 Promises 和 Time 有个基本的使用了解,核心代码用于生产

文章格式:

  1. 带编号的题目
  2. 简单的题目描述(官网的题目描述有时读不懂,完整版请移步官网)
  3. 代码片段(可以通过所有用例)

2723. 两个 Promise 对象相加

给你两个 Promise 对象(比如 promise1 和 promise2),每个 Promise 最终都会解析成一个数字。

你需要写一个函数,同时等待这两个 Promise 完成,然后把它们解析出来的两个数字相加,最后返回一个新的 Promise,这个新 Promise 会解析为相加的结果。

js 复制代码
/**
 * @param {Promise} promise1
 * @param {Promise} promise2
 * @return {Promise}
 */
var addTwoPromises = async function (promise1, promise2) {
  const [val1, val2] = await Promise.all([promise1, promise2]);
  return val1 + val2;
}; // 优雅

/**
 * addTwoPromises(Promise.resolve(2), Promise.resolve(2))
 *   .then(console.log); // 4
 */

2621. 睡眠函数

写一个"睡眠函数",它接受一个毫秒数作为参数,让程序"睡"一会儿(等待指定的时间),然后什么都不返回(或者返回一个 Promise,在等待完成后解析)

js 复制代码
/**
 * @param {number} millis
 * @return {Promise}
 */
async function sleep(millis) {
  return new Promise((resolve) => setTimeout(resolve, millis));
}

/**
 * let t = Date.now()
 * sleep(100).then(() => console.log(Date.now() - t)) // 100
 */

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

你要创建一个"双计时器"系统:

主要功能:

  1. 主任务延迟 :函数 fnt 毫秒后执行
  2. 自动取消机制 :在 cancelTimeMs 毫秒后会自动调用取消函数
  3. 手动取消:可以提前手动取消主任务
js 复制代码
/**
 * @param {Function} fn
 * @param {Array} args
 * @param {number} t
 * @return {Function}
 */
function cancellable(fn, args, t) {
  // 用 setTimeout 安排 fn 执行
  const timerId = setTimeout(() => {
    fn(...args);
  }, t);

  // 返回的 cancelFn 函数
  // 当它被调用时,清除定时器,阻止 fn 执行
  return function cancelFn() {
    clearTimeout(timerId);
  };
}

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

2725. 间隔取消

你要创建一个"定时重复执行 + 自动停止"的系统:

核心功能:

  1. 立即执行 :函数 fn 立即用 args 参数执行一次
  2. 间隔重复 :之后每隔 t 毫秒重复执行一次
  3. 自动停止 :在 cancelTimeMs 毫秒后自动停止所有执行
  4. 返回控制:返回一个取消函数(虽然会自动取消)
js 复制代码
/**
 * @param {Function} fn
 * @param {Array} args
 * @param {number} t
 * @return {Function}
 */
var cancellable = function (fn, args, t) {
  fn(...args);
  let timer = setInterval(fn, t, ...args);
  return () => clearInterval(timer);
};

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

2637. 有时间限制的 Promise 对象

你要创建一个"带超时控制的异步函数包装器":

核心功能:

  1. 正常执行 :让原异步函数 fn 正常执行
  2. 时间限制 :如果 fnt 毫秒内完成,返回结果
  3. 超时处理 :如果 fn 执行超过 t 毫秒,抛出错误 "Time Limit Exceeded"
  4. 参数传递:正确传递所有参数给原函数
js 复制代码
/**
 * @param {Function} fn
 * @param {number} t
 * @return {Function}
 */
function timeLimit(fn, t) {
  return async function (...args) {
    // 创建一个 Promise,用于表示"超时"
    const timeoutPromise = new Promise((_, reject) => {
      setTimeout(() => {
        reject("Time Limit Exceeded");
      }, t);
    });

    // 同时运行 fn 和超时计时器
    // 谁先完成,就用谁的结果
    return Promise.race([
      fn(...args), // 执行原始异步函数
      timeoutPromise, // 超时后触发 reject
    ]);
  };
}

/**
 * const limited = timeLimit((t) => new Promise(res => setTimeout(res, t)), 100);
 * limited(150).catch(console.log) // "Time Limit Exceeded" at t=100ms
 */

2622. 有时间限制的缓存

请你设计一个有时间限制的缓存(Time Limited Cache)类,该类应该支持以下操作:

方法定义:

  1. set(key, value, duration)

    • 接受一个整数键 key,一个整数值 value 和一个以毫秒为单位的持续时间 duration
    • 在指定的持续时间 duration 后,该键值对自动失效
    • 如果该键已经存在且未过期,则更新其值和持续时间
    • 如果相同的未过期键已经存在,该方法将返回 true ,否则返回 false
  2. get(key)

    • 如果键 key 存在且未过期,返回对应的值
    • 如果键不存在或已过期,返回 -1
  3. count()(可选,部分变体)

    • 返回当前未过期的键值对数量
js 复制代码
var TimeLimitedCache = function () {
  this.cache = new Map(); // 使用Map存储键值对和过期时间
};

/**
 * @param {number} key
 * @param {number} value
 * @param {number} duration time until expiration in ms
 * @return {boolean} if un-expired key already existed
 */
TimeLimitedCache.prototype.set = function (key, value, duration) {
  const currentTime = Date.now();
  const expirationTime = currentTime + duration; // 存储过期时间戳

  // 检查键是否已存在且未过期
  const existing = this.cache.get(key);
  const isExisting = existing && existing.expirationTime > currentTime;

  // 设置或更新值
  this.cache.set(key, {
    value: value,
    expirationTime: expirationTime,
  });

  return !!isExisting; // 返回是否存在未过期的键
};

/**
 * @param {number} key
 * @return {number} value associated with key
 */
TimeLimitedCache.prototype.get = function (key) {
  const currentTime = Date.now();
  const item = this.cache.get(key);

  // 如果键不存在或已过期,返回-1
  if (!item || item.expirationTime <= currentTime) {
    return -1;
  }

  return item.value; // 返回未过期的值
};

/**
 * @return {number} count of non-expired keys
 */
TimeLimitedCache.prototype.count = function () {
  const currentTime = Date.now();
  let count = 0;

  // 遍历所有键,统计未过期的数量
  for (const [key, item] of this.cache) {
    if (item.expirationTime > currentTime) {
      count++;
    }
  }

  return count;
};

2627. 函数防抖

你要创建一个"防抖函数",就像电梯关门按钮:

核心功能:

  1. 延迟执行 :函数调用后不会立即执行,而是延迟 t 毫秒
  2. 重置计时:如果在延迟期间再次调用,重新开始计时
  3. 最终执行 :只有在最后一次调用后的 t 毫秒内没有新调用,才会真正执行
js 复制代码
/**
 * @param {Function} fn
 * @param {number} t milliseconds
 * @return {Function}
 */
var debounce = function (fn, t) {
  let timeoutId;

  return function (...args) {
    // 清除之前的定时器(如果存在)
    if (timeoutId) {
      clearTimeout(timeoutId);
    }

    // 设置新的定时器,延迟 t 毫秒后执行 fn
    timeoutId = setTimeout(() => {
      fn.apply(this, args); // 保持 this 上下文和参数
    }, t);
  };
};

2721. 并行执行异步函数

你要自己实现一个 Promise.all 的功能:

核心功能:

  1. 并行执行:同时执行所有异步函数(不按顺序等待)
  2. 全部成功:所有 Promise 都成功时,返回结果数组(保持原始顺序)
  3. 快速失败:任何一个 Promise 失败,立即拒绝(返回第一个错误)
  4. 不用 Promise.all:需要自己实现这个功能
js 复制代码
/**
 * @param {Array<Function>} functions
 * @return {Promise<any>}
 */
var promiseAll = function (functions) {
  return new Promise((resolve, reject) => {
    const n = functions.length;
    const results = new Array(n);
    let completedCount = 0;

    // 如果数组为空,立即resolve空数组
    if (n === 0) return resolve(results);

    functions.forEach((fn, index) => {
      // 执行每个函数获取Promise
      fn()
        .then((result) => {
          // 将结果放在正确的位置
          results[index] = result;
          completedCount++;

          // 当所有Promise都完成时,resolve结果数组
          if (completedCount === n) {
            resolve(results);
          }
        })
        .catch((error) => {
          // 任何一个Promise失败,立即reject
          reject(error);
        });
    });
  });
};

/**
 * const promise = promiseAll([() => new Promise(res => res(42))])
 * promise.then(console.log); // [42]
 */
相关推荐
墨染点香3 小时前
LeetCode 刷题【71. 简化路径】
算法·leetcode·职场和发展
知彼解己3 小时前
【算法】四大基础数据结构
数据结构·算法
老一岁3 小时前
希尔排序详解
数据结构·算法·排序算法
lifallen3 小时前
KafkaStreams 计算图节点设计:ProcessorNode、SourceNode、SinkNode
java·数据结构·算法·kafka·apache
索迪迈科技3 小时前
java后端工程师进修ing(研一版‖day42)
java·开发语言·学习·算法
萌萌哒草头将军3 小时前
Node.js v24.8.0 新功能预览!🚀🚀🚀
前端·javascript·node.js
名誉寒冰3 小时前
LeetCode 24 两两交换链表中的节点( 迭代与递归)
算法·leetcode·链表
小欣加油3 小时前
leetcode LCR 170.交易逆序对的总数
数据结构·c++·算法·leetcode·职场和发展·排序算法
太空游走的鱼3 小时前
Vue3 + Vite + Element Plus web转为 Electron 应用,解决无法登录、隐藏自定义导航栏
javascript·electron·vue3·管理系统·element plsu