实现一个符合 Promise/A+ 规范的 MyPromise

本文详细介绍了如何实现一个符合Promise/A+规范的MyPromise,并涵盖了resolve、reject、all、race等核心方法。通过代码示例深入理解Promise的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Promise

实现一个符合 Promise/A+ 规范的 MyPromise,并实现 resolve、reject、all、race、defer、deferred等静态方法。

MyPromise

  1. 作用:创建 MyPromise实例。Promise
  2. MyPromise接收一个回掉函数 executor
  3. MyPromise状态
    • pending
      • 可以转换成 fulfilled 或 rejected
    • fulfilled
      • 不可改变成其他状态
    • rejected
      • 不可改变成其他状态
  4. onFulfilledCallbacksonRejectedCallbacks
    • 两个数组,数组每一项是一个函数。分别接收then里面的第一个参数和第二个参数。
    • 状态是 pending 的回掉函数。
  5. resolve
    • promise的状态是fulfilled异常是的处理函数
    • 接收 value 参数
      • 如果是promise,执行then
      • 如果不是promise,把value做为参数传给onFulfilledCallbacks里的每个函数。
  6. reject
    • promise的状态是rejected异常是的处理函数
    • 接收 reason 参数,把reason做为参数传给onRejectedCallbacks里的每个函数。
  7. 执行 executor,如果有异常,抛给reject
  8. 因为Promise是在同步代码执行完成后再执行,所以要把Mypromise的执行方法resolvereject放在异步队列里
function MyPromise(executor) {
    if (typeof executor !== 'function') {
        throw new TypeError('Promise resolver ' + executor + ' is not a function');
    }
    let self = this;
    this.status = 'pending';
    this.value = undefined;
    this.reason = undefined;
    this.onFulfilledCallbacks = [];
    this.onRejectedCallbacks = [];
    function resolve(value) {
        if (value instanceof MyPromise) {
            return value.then(resolve, reject);
        }
        if (self.status === 'pending') {
            self.value = value;
            self.status = 'fulfilled';
            self.onFulfilledCallbacks.forEach(item => item(value));
        }
    }
    function reject(reason) {
        if (self.status === 'pending') {
            self.reason = reason;
            self.status = 'rejected';  
            self.onRejectedCallbacks.forEach(item => item(reason));
        }
    }
    try {
        executor(resolve, reject);
    } catch (e) {
        reject(e);
    }
}

复制代码

MyPromise.prototype.then

  1. 作用:接收两个函数参数,第一个函数的参数是 resolve传入的参数,第二个参数是 reject传入的参数。Promise#then
  2. onFulfilled
    • MyPromise 成功时执行的方法
    • resolve 的参数会作为value传给 onFulfilled
  3. onRejected
    • MyPromise 失败时执行的方法
    • reject 的参数会作为value传给 onRejected
  4. 返回一个 MyPromise 实例 newPromise,方便链式调用
  5. 对三种状态分别处理
    • 每个状态中创建 newPromise
    • fulfilled
      • 直接执行 onFulfilled,返回值x
      • newPromisex以及newPromise里的resolvereject做为参数传给 resolutionPromise
      • 把 MyPromise 的参数放在异步队列里
    • rejected
      • 直接执行 onRejected,返回值x
      • newPromisex以及newPromise里的resolvereject做为参数传给 resolutionPromise
      • 把 MyPromise 的参数放在异步队列里
    • pending
      • 状态待定,把fulfilledrejected里的异步函数分别加到 onFulfilledCallbacksonRejectedCallbacks的最后一位
  6. resolutionPromise 后面细说
  7. catch捕获异常,执行 reject
MyPromise.prototype.then = function (onFulfilled, onRejected) {
    let self = this;
    typeof onFulfilled !== 'function' && (onFulfilled = function (value) {
        return value;
    });
    typeof onRejected !== 'function' && (onRejected = function (reason) {
        throw reason;
    });
    let newPromise;
    /**
     *  分别处理实例的三种状态
     */
    if (self.status === 'fulfilled') {
        newPromise = new MyPromise(function (resolve, reject) {
            setTimeout(function () {
                try {
                    let x = onFulfilled(self.value);
                    resolutionPromise(newPromise, x, resolve, reject);
                } catch (e) {
                    reject(e);
                }
            });
        });
    }
    if (self.status === 'rejected') {
        newPromise = new MyPromise(function (resolve, reject) {
            setTimeout(function () {
                try {
                    let x = onRejected(self.reason);
                    resolutionPromise(newPromise, x, resolve, reject);
                } catch (e) {
                    reject(e);
                }
            });
        });
    }
    if (self.status === 'pending') {
        newPromise = new MyPromise(function (resolve, reject) {
            self.onFulfilledCallbacks.push(function (value) {
                setTimeout(function () {
                    try {
                        let x = onFulfilled(value);
                        resolutionPromise(newPromise, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                });
            });
            self.onRejectedCallbacks.push(function (reason) {
                setTimeout(function () {
                    try {
                        let x = onRejected(reason);
                        resolutionPromise(newPromise, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                });
            });
        });
    }
    return newPromise;
};

复制代码

MyPromise.prototype.catch

  1. 作用:捕获异常
  2. 返回 MyPromise
MyPromise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected);
};
复制代码

The Promise Resolution Procedure

  1. Promise解析过程,是以一个 promise、一个值 xresolve, reject做为参数的抽象过程
  2. promise 等于 xreject 抛出异常 new TypeError('循环引用')
  3. x如果不是对象(不包括 null)或者函数,执行 resolve(x)
  4. 获取 x.then 赋值给 then
    • then 如果是 function
      • x做为 this 调用then,第一个参数是 resolvePromise,第二个参数是 rejectPromise
      • resolvePromiserejectPromise只有第一次调用有效
      • resolvePromise参数为 y,执行 resolutionPromise(promise, y, resolve, reject)
      • rejectPromise参数为 r,执行 reject(r)
    • then 如果不是 function
      • 执行 resolve(x)
  5. 用捕获上一步的异常
    • 执行 reject(e)
    • 如果执行过 resolvePromiserejectPromise,忽略
function resolutionPromise(promise, x, resolve, reject) {
    if (promise === x) {
        reject(new TypeError('循环引用'));
    }
    let then, called;
    if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
        try {
            then = x.then;
            if (typeof then === 'function') {
                then.call(x, function (y) {
                    if (called)
                        return;
                    called = true;
                    resolutionPromise(promise, y, resolve, reject);
                }, function (r) {
                    if (called)
                        return;
                    called = true;
                    reject(r);
                })
            } else {
                resolve(x);
            }
        } catch (e) {
            if (called)
                return;
            reject(e);
        }
    } else {
        resolve(x);
    }
}
复制代码

MyPromise 静态方法

MyPromise.all
MyPromise.all = function (promises) {
    let called = false;
    return new MyPromise(function (resolve, reject) {
        let newArr = [], count = 0;
        for (let i = 0; i < promises.length; i++) {
            let item = promises[i];
            if (!(item instanceof MyPromise)) {
                item = MyPromise.resolve(item);
            }
            item.then(function (data) {
                if (!called) {
                    newArr[i] = data;
                    if (i == count) {
                        resolve(newArr);
                        count++;
                    }
                }
            }, function (e) {
                if (!called) {
                    reject(e);
                    called = true;
                }
            });
        }
    });
};
复制代码
MyPromise.race
MyPromise.race = function (promises) {
    return new MyPromise(function (resolve, reject) {
        let called = false;
        for (let i = 0; i < promises.length; i++) {
            let item = promises[i];
            if (!(item instanceof MyPromise)) {
                item = MyPromise.resolve(item);
            }
            item.then(function (data) {
                if (!called) {
                    resolve(data);
                    called = true;
                }
            }, function (e) {
                if (!called) {
                    reject(e);
                    called = true;
                }
            });
        }
    })
};
复制代码
MyPromise.resolve
MyPromise.resolve = function (value) {
    if (value instanceof MyPromise) {
        return value;
    }
    return new MyPromise(function (resolve, reject) {
        if (typeof value !== null && typeof value === 'object' && typeof value.then === 'function') {
            value.then();
        } else {
            resolve(value);
        }
    })
};
复制代码
MyPromise.reject
MyPromise.reject = function (e) {
    return new MyPromise(function (resolve, reject) {
        reject(e);
    })
};
复制代码

test

  • npm i -g promises-aplus-tests
  • promises-aplus-tests Promise.js
源码
参考资料
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值