扩展Javascript承诺并在构造函数中解析或拒绝它 [英] Extend Javascript promise and resolve or reject it inside constructor

查看:128
本文介绍了扩展Javascript承诺并在构造函数中解析或拒绝它的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用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:


  1. 子类构造函数执行两次

  2. 未捕获的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 of resolve and reject arguments passed to it for later use.
  • "later use" covers resolving or rejecting the promise returned by then asynchronously when monitoring execution of onfulfilled or onrejected handlers (later) to see if they return a value (which resolves the then 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 拒绝功能参数。这是然后方法代码的内部要求。

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆