简体   繁体   English

扩展`Promise`并改变`then`签名

[英]Extending `Promise` and change `then` signature

I want to extend Promise and change the then signature so its callback receives two values. 我想扩展Promise并更改then签名,以便其回调接收两个值。 I tried different approaches two of which are documented and tested here . 我尝试了不同的方法,其中两个在此处记录和测试。 Sadly, I get various errors or the resulting class does not behave like a Promise. 可悲的是,我得到了各种错误,或者由此产生的类不像Promise。

Approach 1: Wrapping a native Promise 方法1: 包装本机承诺

export class MyWrappedPromise {
  constructor(data) {
    this.data = data;
    this.promise = new Promise(evaluate.bind(data));
  }

  then(callback) {
    this.promise.then(() => callback(this.data, ADDITIONAL_DATA));
  }

  catch(callback) {
    this.promise.catch(callback);
  }
}

Approach 2: Extending native Promises 方法2: 扩展本机承诺

export class MyExtendedPromise extends Promise {

  constructor(executor, data) {
    super(executor);
    this.data = data;
  }

  static create(data) {
      return new MyExtendedPromise(evaluate.bind(data), data);
  }

  then(callback) {
    return super.then(() => callback(this.data, ADDITIONAL_DATA));
  }
}

Does anyone have any suggestion on what I am doing wrong? 有没有人对我做错了什么有任何建议? Feel free to create a PR on GitHub. 随意在GitHub上创建PR。

thanks 谢谢

------------------- Edit --------------------- -------------------编辑---------------------

Some Additional code and info to make the code above more understandable without looking at the code and tests on Github. 一些额外的代码和信息使得上面的代码更容易理解,而无需查看Github上的代码和测试。

evaluate is just the Promise executor function. evaluate只是Promise执行器函数。 I extracted it out so I can keep it consistent across all my implementations and tests. 我把它解压出来,这样我就可以在所有的实现和测试中保持一致。 It may look convoluted but it's structured that way to simulate my "real" project. 它可能看起来很复杂,但它的结构是模拟我的“真实”项目。

export function evaluate(resolve, reject) {
  const data = this;
  function getPromise(data) {
    return !!data ? Promise.resolve(data) : Promise.reject(new Error("Error"));
  }

  getPromise(data)
    .then(resolve)
    .catch(reject);
}

ADDITIONAL_DATA is just a string to simulate the second value in the callback. ADDITIONAL_DATA只是一个字符串,用于模拟回调中的第二个值。 It's also extracted to be consistent across all versions and tests. 它也被提取为在所有版本和测试中保持一致。

------------------- Edit 2--------------------- -------------------编辑2 ---------------------

Errors that come up depending on the solution 根据解决方案出现的错误

  • catch is not accessible catch是无法访问的
  • A lot of UnhandledPromiseRejectionWarning: warnings because errors/rejects are not getting propagated up correctly. 很多UnhandledPromiseRejectionWarning:警告,因为错误/拒绝没有正确传播。
  • Errors/rejects are getting thrown too early and don't even reach the rejects checks in my test suites 错误/拒绝被过早抛出,甚至没有达到我的测试套件中的rejects检查

I don't understand very well why you do have a factory method, instead of using directly the constructor. 我不太清楚为什么你有一个工厂方法,而不是直接使用构造函数。

Do you mean something like this? 你的意思是这样的吗?

 class MyExtendedPromise extends Promise { constructor(executor, data) { super(executor); this.data = data; } then(callback, test) { console.log('passed new parameter in then:', test); console.log('additional data:', this.data); return super.then(data => callback(data, test)); } } new MyExtendedPromise((resolve, reject) => { setTimeout(() => resolve(true), 2000); }, 'other additional data').then(data => console.log('my then', data), 'hello world'); 

You have problems (especially with unhandled rejections) because you are not implementing the then interface correctly. 您有问题(尤其是未处理的拒绝),因为您没有正确实现then接口。 Remember that .catch(onRejected) is just an alias for .then(undefined, onRejected) , and then with two parameters is the actual core method of every promise . 请记住.catch(onRejected)只是.catch(onRejected) .then(undefined, onRejected)的别名, then有两个参数每个promise的实际核心方法

You were always ignoring the second argument, so no rejection ever got handled. 你总是忽略第二个论点,所以没有任何拒绝处理。 You need to write 你需要写

then(onFulfilled, onRejected) {
  return super.then(res => onFulfilled(res, this.ADDITIONAL_DATA), onRejected);
  // or `this.promise.then` instead of `super.then`
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM