在 JavaScript 中扩展 Promise [英] Extending a Promise in javascript
问题描述
我正在学习 JavaScript 中的类和继承.我认为以下是扩展现有对象的相当标准的方式,因为我从 关于 Object.create 的 MDN 文档
I'm learning about classes and inheritance in javascript. I thought that the following is a fairly standard way of extending an existing object as I got the style from the MDN docs on Object.create
我期待看到好的"然后是耶!你好'在控制台中,但我却出现了这个错误:
I was expecting to see 'ok' and then 'Yay! Hello' in the console, but instead I go this error:
Uncaught TypeError: #<MyPromise> is not a promise
at new MyPromise (<anonymous>:5:17)
at <anonymous>:19:6
看起来 Promise 构造函数正在抛出异常,因为它可以告诉我给它初始化的对象不是一个简单的 Promise.
It looks like the Promise constructor is throwing an exception because it can tell that the object I've given it to initialise isn't a straightforward Promise.
我希望 Promise 构造函数将我的对象初始化为 Promise 对象,这样我就可以扩展该类.他们为什么不编写 Promise 构造函数来使用这种常见模式?难道我做错了什么?干杯看看!
I want the Promise constructor to initialise my object as if it was a Promise object, so I can then extend the class. Why wouldn't they write the Promise constructor to work with this common pattern? Am I doing something wrong? Cheers for taking a look!
MyPromise = function(message, ok) {
var myPromise = this;
this.message = message;
this.ok = ok;
Promise.call(this, function(resolve, reject) {
if(this.ok) {
console.log('ok');
resolve(myPromise.message);
} else {
console.log('not ok');
reject(myPromise.message);
}
});
};
MyPromise.prototype = Object.create(Promise.prototype);
MyPromise.prototype.constructor = MyPromise;
(new MyPromise('Hello', true))
.then(function(response) {console.log('Yay! ' + response);})
.except(function(error) {console.log('Aww! ' + error);});
我最初试图制作一个您可以使用的 BatchAjax 类:
I was originally trying to make a BatchAjax class that you could use like:
(new BatchAjax([query1, query2]))
.then(function(response) {console.log('Fires when all queries are complete.');});
真的只是有点好玩.
推荐答案
原生 Promise
类(如 Error
和 Array
)不能被使用旧的 ES5 风格的子类化机制正确子类化.
The native Promise
class (like Error
and Array
) cannot be correctly subclassed with the old ES5-style mechanism for subclassing.
子类Promise
的正确方法是通过class
语法:
The correct way to subclass Promise
is through class
syntax:
class MyPromise extends Promise {
}
示例:
class MyPromise extends Promise {
myMethod() {
return this.then(str => str.toUpperCase());
}
}
// Usage example 1
MyPromise.resolve("it works")
.myMethod()
.then(result => console.log(result))
.catch(error => console.error(error));
// Usage example 2
new MyPromise((resolve, reject) => {
if (Math.random() < 0.5) {
resolve("it works");
} else {
reject(new Error("promise rejected; it does this half the time just to show that part working"));
}
})
.myMethod()
.then(result => console.log(result))
.catch(error => console.error(error));
如果您的目标是在没有 class
的情况下做到这一点,主要使用 ES5 级别的功能,您可以通过 Reflect.construct
.请注意,Reflect.construct
是 ES2015 的一个特性,就像 class
,但你似乎更喜欢 ES5 风格的创建类.
If it's your goal to do that without class
, using mostly ES5-level features, you can via Reflect.construct
. Note that Reflect.construct
is an ES2015 feature, like class
, but you seem to prefer the ES5 style of creating classes.
您可以这样做:
// Create a constructor that uses `Promise` as its super and does the `super` call
// via `Reflect.construct`
const MyPromise = function(executor) {
return Reflect.construct(Promise, [executor], MyPromise);
};
// Make `MyPromise` inherit statics from `Promise`
Object.setPrototypeOf(MyPromise, Promise);
// Create the prototype, add methods to it
MyPromise.prototype = Object.create(Promise.prototype);
MyPromise.prototype.constructor = MyPromise;
MyPromise.prototype.myMethod = function() {
return this.then(str => str.toUpperCase());
};
然后像Promise
一样使用:
MyPromise.resolve("it works")
.myMethod()
.then(result => console.log(result))
.catch(error => console.error(error));
或
new MyPromise(resolve => resolve("it works"))
.myMethod()
.then(result => console.log(result))
.catch(error => console.error(error));
等
现场示例:
// Create a constructor that uses `Promise` as its super and does the `super` call
// via `Reflect.construct`
const MyPromise = function(executor) {
return Reflect.construct(Promise, [executor], MyPromise);
};
// Make `MyPromise` inherit statics from `Promise`
Object.setPrototypeOf(MyPromise, Promise);
// Create the prototype, add methods to it
MyPromise.prototype = Object.create(Promise.prototype);
MyPromise.prototype.constructor = MyPromise;
MyPromise.prototype.myMethod = function() {
return this.then(str => str.toUpperCase());
};
// Usage example 1
MyPromise.resolve("it works")
.myMethod()
.then(result => console.log(result))
.catch(error => console.error(error));
// Usage example 2
new MyPromise((resolve, reject) => {
if (Math.random() < 0.5) {
resolve("it works");
} else {
reject(new Error("promise rejected; it does this half the time just to show that part working"));
}
})
.myMethod()
.then(result => console.log(result))
.catch(error => console.error(error));
如果你想避免改变MyPromise
的原型,你可以把静态属性复制过来,但不是一回事:
If you want to avoid changing the prototype of MyPromise
, you can copy the static properties over, but it's not quite the same thing:
// Create a constructor that uses `Promise` as its super and does the `super` call
// via `Reflect.construct`
const MyPromise = function(executor) {
return Reflect.construct(Promise, [executor], MyPromise);
};
// Assign the statics (`resolve`, `reject`, etc.) to the new constructor
Object.assign(
MyPromise,
Object.fromEntries(
Reflect.ownKeys(Promise)
.filter(key => key !== "length" && key !== "name")
.map(key => [key, Promise[key]])
)
);
// Create the prototype, add methods to it
MyPromise.prototype = Object.create(Promise.prototype);
MyPromise.prototype.constructor = MyPromise;
MyPromise.prototype.myMethod = function() {
return this.then(str => str.toUpperCase());
};
使用它当然是一样的.
现场示例:
// Create a constructor that uses `Promise` as its super and does the `super` call
// via `Reflect.construct`
const MyPromise = function(executor) {
return Reflect.construct(Promise, [executor], MyPromise);
};
// Assign the statics (`resolve`, `reject`, etc.) to the new constructor
Object.assign(
MyPromise,
Object.fromEntries(
Reflect.ownKeys(Promise)
.filter(key => key !== "length" && key !== "name")
.map(key => [key, Promise[key]])
)
);
// Create the prototype, add methods to it
MyPromise.prototype = Object.create(Promise.prototype);
MyPromise.prototype.constructor = MyPromise;
MyPromise.prototype.myMethod = function() {
return this.then(str => str.toUpperCase());
};
// Usage example 1
MyPromise.resolve("it works")
.myMethod()
.then(result => console.log(result))
.catch(error => console.error(error));
// Usage example 2
new MyPromise((resolve, reject) => {
if (Math.random() < 0.5) {
resolve("it works");
} else {
reject(new Error("promise rejected; it does this half the time just to show that part working"));
}
})
.myMethod()
.then(result => console.log(result))
.catch(error => console.error(error));
这篇关于在 JavaScript 中扩展 Promise的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!