如何编写适用于 Promise.resolve() 的 Promise 的 polyfill?

问题描述 投票:0回答:1

我正在尝试编写一个 Promise Polyfill 以更好地理解 Promise。 我在网上搜索了一下,找到了一段我能在一定程度上理解的代码。

function CustomPromise(executor) {
var state=PENDING;
var value = null;
var handlers=[];
var catchers = [];

function resolve(result) {
    if(state!==PENDING) return;

    state=FULFILLED;
    value = result;

    handlers.forEach((h)=>h(value));    //this line
}

function reject(error) {
    if(state!==PENDING)return;

    state=REJECTED;
    value=error;
    catchers.forEach(c=>c(value));  // this line
}

this.then = function(successCallback) {
    if(state === FULFILLED) {
        successCallback(value);
    }else {
        handlers.push(successCallback);
    }
    return this;
}

this.catch = function(failureCallback) {
    if(state===REJECTED){
        failureCallback(value)
    } else {
        catchers.push(value);
    }
}
executor(resolve,reject);
}

即使这样我也无法理解处理程序和捕手的使用。据说,它们是为了应对承诺没有兑现或被拒绝的情况。解释这两行也会有所帮助。 现在,上述实现的实际问题是它在像

let p1 = Promise.resolve("Hello World");
这样使用时不起作用。我尝试将其转换为基于类的,但我无法做到这一点。 我的尝试:

class CustomPromise {
constructor(callback){
    this.state = PENDING;
    this.executor = callback;
    this.value = null;
    this.handlers = [];
    this.catchers = [];
    this.then = function(successCallback) {
        if(this.state === FULFILLED) {
            successCallback(this.value);
        }else {
            this.handlers.push(successCallback);
        }
        return this;
    };

    this.catch = function(failureCallback) {
        if(this.state===REJECTED){
            failureCallback(this.value)
        } else {
            this.catchers.push(this.value);
        }
    };
}

static resolve(result) {
    if(this.state!==PENDING) return;

    this.state=FULFILLED;
    this.value = result;

    this.handlers.forEach((h)=>h(this.value));
    // return new CustomPromise( function ( fulfil ) {
    //     fulfil( value );
    // });
}

static reject(error) {
    if(this.state!==PENDING)return;

    this.state=REJECTED;
    this.value=error;
    this.catchers.forEach(c=>c(this.value));
}

// executor(resolve,reject);
}

有人可以更正功能方法,使其适用于

 CustomPromise.resolve()
场景,或者对我基于类的方法进行更正也将不胜感激。 编辑:尝试过
CustomPromise.prototype.resolve = function(error) {...}
仍然出现同样的错误
CustomPromise.resolve is not a function
EDIT2:在基于类的方法中,我无法实现 executor 回调。我只希望其中一种方法适用于像
Promise.resolve()

这样的情况
javascript promise es6-promise
1个回答
3
投票

要扩展

CustomPromise
的第一个(工作)版本,请在您拥有的(非工作)类版本中的注释掉代码中添加您似乎一直在尝试使用的代码。但它有两个小问题。尽管如此,使用
new CustomPromise
的想法是正确的:

CustomPromise.resolve = value => new CustomPromise(fulfil => fulfil(value));
CustomPromise.reject = error => new CustomPromise((_, reject) => reject(error));

因此,如果您将其添加到

CustomPromise
函数定义下方,它将起作用。

其次,由于

catchers
应该有回调函数,所以你不应该将
value
推送给它,而是
failureCallback
:

const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";

function CustomPromise(executor) {
    var state=PENDING;
    var value = null;
    var handlers=[];
    var catchers = [];

    function resolve(result) {
        if(state!==PENDING) return;

        state=FULFILLED;
        value = result;

        handlers.forEach((h)=>h(value));
    }

    function reject(error) {
        if(state!==PENDING)return;

        state=REJECTED;
        value=error;
        catchers.forEach(c=>c(value));
    }

    this.then = function(successCallback) {
        if(state === FULFILLED) {
            successCallback(value);
        }else {
            handlers.push(successCallback);
        }
        return this;
    }

    this.catch = function(failureCallback) {
        if(state===REJECTED){
            failureCallback(value)
        } else {
            catchers.push(failureCallback); // Fix
        }
    }
    executor(resolve,reject);
}

// Added:
CustomPromise.resolve = value => new CustomPromise(fulfil => fulfil(value));
CustomPromise.reject = error => new CustomPromise((_, reject) => reject(error));

// Demo
let p = CustomPromise.resolve(42);
let q = CustomPromise.reject("custom error");
p.then(value => console.log("p", value));
q.catch(error => console.log("q", error));

免责声明:此 Polyfill 不符合 Promises/A+ 规范,但它会符合

Promise
的 ECMAScript 规范。

它存在的一些问题:

  • 它允许同步执行
    then
    回调。
    then
    回调永远不应同步执行,而应始终通过排队作业调用(即异步)。
  • catch
    方法错误地返回未定义。它应该返回一个承诺。
  • then
    方法错误地返回与调用它相同的承诺。它应该返回一个不同的承诺,该承诺将通过回调返回的值进行解析。
  • then
    方法忽略第二个参数。它应该采用第二个函数作为拒绝回调(如
    catch
    )。
  • 当 Promise 通过 thenable 解决时,thenable 被错误地用作履行值。这不是它应该如何工作的。 Promise 的一个非常重要的方面是 Promise chain,即当一个 Promise 解析为另一个 Promise(或 thenable)时,它会被“锁定”到第二个 Promise,这样它将遵循第二个 Promise 解析的方式。

有很多正确的实现可以找到。我发布了我自己的 Promises/A+ 兼容实现在此答案中。它没有

resolve
reject
静态方法,但它需要与上面给出的相同的附加代码。

© www.soinside.com 2019 - 2024. All rights reserved.