[英]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
是无法访问的 UnhandledPromiseRejectionWarning:
warnings because errors/rejects are not getting propagated up correctly. UnhandledPromiseRejectionWarning:
警告,因为错误/拒绝没有正确传播。 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.