扩展Javascript承诺并在构造函数中解析或拒绝它 [英] Extend Javascript promise and resolve or reject it inside constructor
问题描述
我想用ES6语法扩展本机Javascript Promise类,并能够在子类构造函数中调用一些异步函数。基于异步函数结果,承诺必须被拒绝或解决。
I want to extend native Javascript Promise class with ES6 syntax, and be able to call some asynchronous function inside the subclass constructor. Based on async function result the promise must be either rejected or resolved.
然而,当然后
时会发生两件奇怪的事情函数被调用:
However, two strange things happen when then
function is called:
- 子类构造函数执行两次
- 未捕获的TypeError:Promise解析或拒绝函数不可调用抛出错误
class MyPromise extends Promise {
constructor(name) {
super((resolve, reject) => {
setTimeout(() => {
resolve(1)
}, 1000)
})
this.name = name
}
}
new MyPromise('p1')
.then(result => {
console.log('resolved, result: ', result)
})
.catch(err => {
console.error('err: ', err)
})
推荐答案
推理很简单但不一定是不言而喻的。
The reasoning is simple but not necessarily self evident.
-
.then()
返回一个promise - 如果
然后在Promise的子类上调用
,返回的promise是子类的实例,而不是Promise -
然后
返回的promise是通过调用子类构造函数并传递一个内部执行函数来构造的,该函数记录了resolve
和拒绝
传递给它的参数供以后使用。 - 稍后在监视
onfulfilled
或的执行情况时,使用覆盖解析或拒绝
处理程序(稍后)查看它们是否返回一个值(解析然后
返回的承诺 onrejected然后
返回的promise)或抛出错误(拒绝承诺) 。
.then()
returns a promise- if
then
is called on a subclass of Promise, the returned promise is an instance of the subclass, not Promise itself. - the
then
returned promise is constructed by calling the subclass constructor, and passing it an internal executor function that records the value ofresolve
andreject
arguments passed to it for later use. - "later use" covers resolving or rejecting the promise returned by
then
asynchronously when monitoring execution ofonfulfilled
oronrejected
handlers (later) to see if they return a value (which resolves thethen
returned promise) or throw an error (which rejects the promise).
然后
调用内部获取并记录对 resolve
和拒绝的引用
他们返回的承诺函数。
关于这个问题,
In short then
calls internally obtain and record references to the resolve
and reject
functions of promises they return.
So regarding the question,
new MyPromise( 'p1')
工作正常,是第一次调用子类构造函数。
works fine and is the first call to the subclass constructor.
.then( someFunction)
记录 someFunction
在然后
列表中 new MyPromise
(召回然后
可多次调用)并尝试通过调用
records someFunction
in a list of then
calls made on new MyPromise
(recall then
can be called multiple times) and attempts to create a return promise by calling
new MyPromise( (resolve, reject) => ... /* store resolve reject references */
这是对子类构造函数的第二次调用从然后
代码。期望构造函数(并且确实)同步返回。
This is the second call to the subclass constructor coming from then
code. The constructor is expected to (and does) return synchronously.
从创建返回的承诺返回时, .then
方法进行完整性检查以查看 resolve
和拒绝
以后需要使用的函数实际上是函数。它们应该已经存储(在列表中)以及然后
调用中提供的回调。
On return from creating the promise to return, the .then
method makes an integrity check to see if the resolve
and reject
functions it needs for later use are in fact functions. They should have been stored (in a list) along with callbacks provided in the then
call.
在这种情况下 MyPromise
他们不是。通过然后
传递给 MyPromise
的执行程序甚至都没有被调用。所以然后
方法代码抛出一个类型错误Promise resolve或reject function is not callable - 它无法解析或拒绝它应该返回的promise。
In the case of MyPromise
they are not. The executor passed by then
, to MyPromise
, is not even called. So then
method code throws a type error "Promise resolve or reject function is not callable" - it has no means of resolving or rejecting the promise it is supposed to return.
创建Promise的子类时,子类构造函数必须将执行函数作为其第一个参数,并使用实际 resolve $ c调用执行程序$ c>和
拒绝
功能参数。这是然后
方法代码的内部要求。
When creating a subclass of Promise, the subclass constructor must take an executor function as its first argument, and call the executor with real resolve
and reject
functional arguments. This is internally required by then
method code.
用 MyPromise做一些复杂的事情
,或许检查第一个参数以查看它是否是一个函数并将其作为执行程序调用,如果是,可能是可行的,但不在本答案的范围内!对于显示的代码,编写工厂/库函数可能更简单:
Doing something intricate with MyPromise
, perhaps checking the first parameter to see if it is a function and calling it as an executor if it is, may be feasible but is outside the scope of this answer! For the code shown, writing a factory/library function may be simpler:
function namedDelay(name, delay=1000, value=1) {
var promise = new Promise( (resolve,reject) => {
setTimeout(() => {
resolve(value)
}, delay)
}
);
promise.name = name;
return promise;
}
namedDelay( 'p1')
.then(result => {
console.log('fulfilled, result: ', result)
})
.catch(err => {
console.error('err: ', err)
})
; TLDR
Promise的类扩展不是扩展名。如果是,则需要实现Promise接口并将执行器函数作为第一个参数。您可以使用工厂函数返回异步解析的Promise(如上所述),或 hack 已发布的代码
The class extension to Promise is not an extension. If it were it would need to implement the Promise interface and take an executor function as first parameter. You could use a factory function to return a Promise which is resolved asynchronously (as above), or hack the posted code with
MyPromise.prototype.constructor = Promise
导致 .then
返回一个普通的Promise对象。黑客攻击本身驳斥了类扩展正在发生的想法。
which causes .then
to return a regular Promise object. The hack itself refutes the idea that a class extension is taking place.
这篇关于扩展Javascript承诺并在构造函数中解析或拒绝它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!