leetcode2650. 设计可取消函数 generator和Promise

题目描述:

有时候你会有一个长时间运行的任务,并且你可能希望在它完成之前取消它。为了实现这个目标,请你编写一个名为 cancellable 的函数,它接收一个生成器对象,并返回一个包含两个值的数组:一个 取消函数 和一个 promise 对象。

你可以假设生成器函数只会生成 promise 对象。你的函数负责将 promise 对象解析的值传回生成器。如果 promise 被拒绝,你的函数应将该错误抛回给生成器。

如果在生成器完成之前调用了取消回调函数,则你的函数应该将错误抛回给生成器。该错误应该是字符串 "Cancelled"(而不是一个 Error 对象)。如果错误被捕获,则返回的 promise 应该解析为下一个生成或返回的值。否则,promise 应该被拒绝并抛出该错误。不应执行任何其他代码。

当生成器完成时,您的函数返回的 promise 应该解析为生成器返回的值。但是,如果生成器抛出错误,则返回的 promise 应该拒绝并抛出该错误。

下面的示例展示了你的代码会如何被使用:

js 复制代码
function* tasks() {
  const val = yield new Promise(resolve => resolve(2 + 2));
  yield new Promise(resolve => setTimeout(resolve, 100));
  return val + 1; // calculation shouldn't be done.
}
const [cancel, promise] = cancellable(tasks());
setTimeout(cancel, 50);
promise.catch(console.log); // logs "Cancelled" at t=50ms

相反,如果 cancel() 没有被调用或者在 t=100ms 之后才被调用,那么 promise 应被解析为 5 。

思路

题目要求:

  1. 返回可取消函数
  • 调用取消函数抛出"Cancelled"给生成器(generator.throw("Cancelled"))
  • 解析promise为生成器下一个的value(resolve(generator.next()))
  • 如果发生错误,promise 应该被拒绝并抛出该错误 (reject(err))
  1. 返回Promise
  • 将生成器的 promise 对象解析的值传回生成器(generator.next(ResolvedLastValue)
  • 如果 promise 被拒绝,应将该错误抛回给生成器(Promise.throw(err))
  • 生成器完成时,您的函数返回的 promise 应该解析为生成器返回的值。
  • 如果生成器抛出错误,则返回的 promise 应该拒绝并抛出该错误。

一步一步实现要求就好,对generator不熟悉也可以看看我之前的一篇博客

需要注意的是生成器每次返回的值都是Promise对象,需要等待其完成异步操作

代码

while迭代

js 复制代码
var cancellable = function (generator) {
  let cancel = () => {};
  const promise = new Promise(async (resolve, reject) => {
    cancel = async () => {
      try {
      //抛出"Cancelled"给生成器
        let nextGenerator = generator.throw("Cancelled");
        //解析promise为生成器下一个的value
        resolve(await nextGenerator.value); 
      } catch (cancelError) {
      //拒绝并抛出该错误
        reject(cancelError);
      }
    };

    try {
      let nextGenerator  = generator.next();
      while (!nextGenerator.done) {
        try {
          const resolvedVal = await nextGenerator.value; //注意这里的异步
          // promise 对象解析的值传回生成器
          nextGenerator  = generator.next(resolvedVal);
        } catch (err) {
        //该Promise错误抛回给生成器
          nextGenerator  = generator.throw(err)
        }
      }
      //返回的 promise 解析为生成器返回的值。
      resolve(await nextGenerator.value);
    } catch (generatorError) {
   //生成器抛出错误,则返回的 promise 应该拒绝并抛出该错误。
      reject(generatorError);
    }
  });
  return [cancel, promise];
};
相关推荐
小羊没烦恼!1 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
三十而立洋1 天前
Cookie 详解:从产生到安全,一次讲透
前端·javascript
伞伞悦读1 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python
卡布鲁1 天前
把一个 Vite + Vue3 应用塞进 qiankun (React + Umi3) 主站:十个坑的复盘
前端·javascript·react.js
C语言小火车1 天前
C/C++ 为什么需要编译器?
开发语言·c++
李少兄1 天前
JavaScript 隐式全局变量解析
javascript
旖旎夜光1 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
霍霍的袁1 天前
【C++】map 和 set 的使用 | 从用法到底层
开发语言·c++·学习·visual studio
孙启超1 天前
【AI开发之Rust】第 11 课:智能指针与内部可变性
开发语言·后端·rust
此生决int1 天前
深入理解C++系列(20)——C++11(下)
开发语言·c++