Promise A+实现:当调用then()并且Promise仍然挂起时该怎么办

Promise A+ Implementation: what to do when call then() and the promise is still pending?

本文关键字:Promise 挂起 怎么办 并且 实现 then 调用      更新时间:2023-09-26

一段时间以来,我一直在舒适地使用promise实现。

所以我决定实现我自己的promise库只是为了好玩(并在这个过程中学到一些东西)。

我正在努力遵循Promise A+规范(也许我会省略一些细节,因为我无意将其作为生产代码)。

我的完整代码(仍在进行中)就是这个要点,但相关部分如下。

我在实现then()时遇到了一个问题。当承诺悬而未决时,我根本不知道该怎么办:

Promise.prototype.then = function(onFulfill, onReject) {
    var ret;
    var self = this;
    if (isFulfilled.call(this)) {
        console.log('fulfilled');
        if (isFunction(onFulfill)) {
            return promiseResolution(this, onFulfill(this.value));
        } else {
            return new Promise(function(resolve){
                resolve(self.value);
            });
        }
    } else if (isRejected.call(this)) {
        console.log('rejected');
        if (isFunction(onReject)) {
            return promiseResolution(this, onReject(this.reason));
        } else {
            return new Promise(function(resolve, reject){
                reject(self.reason);
            });
        }
    } else if (isPending.call(this)) {
        console.log('pending');
        enqueueCallback(this.fulfillCallbackQueue, onFulfill);
        enqueueCallback(this.rejectCallbackQueue, onReject);
        // ... what now?
    }
};
function promiseResolution(promise, x) {
    if (promise === x) {
        throw new TypeError('Cannot resolve promise with itself');
    } else if (x instanceof Promise) {
        if (isFulfilled.call(x)) {
            return new Promise(function(resolve, reject){
                resolve(x.value);
            });
        } else if (isRejected.call(x)) {
            return new Promise(function(resolve, reject){
                reject(x.reason);
            });
        } else {
            return x;
        }
    } else {
        return new Promise(function(resolve, reject){
            resolve(x);
        });
    }
}

答案肯定很明显,但我在这里有点不知所措。

编辑:

我已经用我正在编写的测试套件更新了要点。

编辑#2:

我成功地运行了第一个实现的测试。这是我存储代码的git存储库。我会努力不断改进。

感谢@BenjaminGruenbaum。

首先,确保您没有实现A+,除非您有充分的理由这样做。实现一个好的承诺是非常棘手的。

当promise挂起时,将以下内容推送到处理程序数组:

  • 你正在返回的承诺-因为承诺A+要求你检测到一个承诺正在返回并拒绝它
  • 从构造函数中提取的promise的reject函数
  • 从构造函数中提取的promise的解析函数
  • onFulfilled处理程序
  • onRejected处理程序

当返回新承诺的承诺经过解析时,您需要

  • 如果它拒绝了-完成后运行拒绝处理程序和resolve(如果抛出则拒绝)。检查返回值上是否有相同的引用。如果没有处理程序或者它不是函数,则可以传递e => { throw e; }
  • 如果它完成了-完成后运行履行处理程序和resolve(如果抛出则拒绝)。检查返回值上是否有相同的引用。如果没有处理程序或者它不是函数,则可以传递v => v

当然,resolve本身需要进行同化,也需要从外国进行同化。我建议运行promises/A+测试套件,并一点一点地解决它,直到所有测试都通过。