终于,我也会手写Promise A+了

对于 Promise 其实本身并不陌生,可以说是经常使用了,面试题也做了不少,但是对于手动实现一个符合 promise A+规范,我还真的从来没有做过,特此花半天时间好好研究研究。

Promise A+

先来看看promise A+规范。我这仅过了四级的英语水平也是坑坑洼洼的看完了,建议还是都看一下,毕竟正统哈哈。

我简单做了个总结,有错误的话望指正:

  1. state

比较简单,就是有三种状态:

  • pending 可以转为下面两种状态
  • fulfilled 不可改变状态,必须有一个不能改变的 value
  • rejected 不可改变状态,必须有一个不能改变的 reason
  1. then

promise.then(onFulfilled, onRejected);

  • 2.1 onFulfilled,onRejected 都是可选的,如果它们不是函数,就必须被忽略。
  • 2.2 onFulfilled,onRejected 为函数,必须在 promise 转为对应的状态后再传入对应的参数 value/reason 进行调用, 且只能被调用一次
  • 2.3 onFulfilled,onRejected 都是异步执行的
  • 2.4 then 可以被同一个 promise 调用多次
  • 2.5 then 必须返回一个 promise,如果 onFulfilled, onRejected 返回了值 x ,就执行下方的 promise resolve produre
  1. Promise resolve procedure

[[Resolve]](promise, x)

  • 3.1 promise 和 x 是同一个对象,抛出 TypeError 错误

  • 3.2 x 是一个不为 null 的对象或者函数,先让 then 指向 x.then;x.then 不存在抛错 e,用 e 来 reject promise。

    • 3.2.1 then 为函数,调用 then 并使用 x 作为 this,第一个参数 , 第二个参数 rejectPromise; resolvePromise 的结果 y 传入[[Resolve]](promise, y), 如此递归,rejectPromise 的结果 r, 用 r 拒绝 promise
    • 3.2.2 then 不为函数,用 x 来 fulfill promise
  • 3.3 x 不是一个对象或者函数
    用 x 来 fulfill promise

代码实现

// 三种状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected';

// 从new Promise((resolve,rejected) => {}) 切入
class _promise {
    constructor(exector) {
        this.state = PENDING;
        this.value = null;
        this.reason = null;
        // then函数中成功失败回调函数的集合, 这样支持同一个promise实例调用多个then
        this.onFulfilled = [];
        this.onRejected = [];
        try {
            exector(this.resolve, this.reject);
        } catch (e) {
            this.reject(e);
        }
    }
    resolve = value => {
        if (this.state === PENDING) {
            this.state = FULFILLED;
            this.value = value;
            this.onFulfilled.forEach(fn => fn(value));
        }
    };
    reject = reason => {
        if (this.state === PENDING) {
            this.state = REJECTED;
            this.reason = reason;
            this.onRejected.forEach(fn => fn(reason));
        }
    };

    then = (onFulfilled, onRejected) => {
        // 根据规范,如果参数不是函数就忽略,使用默认函数
        onFulfilled =
            typeof onFulfilled === 'function'
                ? onFulfilled
                : function (x) {
                      return x;
                  };
        onRejected =
            typeof onRejected === 'function'
                ? onRejected
                : function (e) {
                      throw e;
                  };
        // 根据贵燃then可以链式调用,返回的也是promise实例
        const promise = new _promise((resolve, reject) => {
            // 创建成功和失败的微任务回调
            const fulfilledTask = () => {
                queueMicrotask(() => {
                    try {
                        const x = onFulfilled(this.value);
                        resolvePromise(promise, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                });
            };
            const rejectedTask = () => {
                queueMicrotask(() => {
                    try {
                        const x = onRejected(this.reason);
                        resolvePromise(promise, x, resolve, reject);
                    } catch (e) {
                        reject(e);
                    }
                });
            };
            // 根据三种状态做不同的处理
            if (this.state === FULFILLED) {
                fulfilledTask();
            } else if (this.state === REJECTED) {
                rejectedTask();
            } else {
                this.onFulfilled.push(fulfilledTask);
                this.onRejected.push(rejectedTask);
            }
        });
        return promise;
    };
}

// 对then中return出来的数据做处理
// 1. x 不能等于 promise 自身, 不然会报错等于死循环
// 2. x 为对象或者函数
// 3. x 为普通值,直接resolve
function resolvePromise(promise, x, resolve, reject) {
    if (promise === x) {
        return reject(new TypeError('type error'));
    }
    if ((typeof x === 'object' || typeof x === 'function') && x !== null) {
        let called;
        try {
            let then = x.then;
            if (typeof then === 'function') {
                then.call(
                    x,
                    y => {
                        if (called) return;
                        called = true;
                        resolvePromise(promise, y, resolve, reject);
                    },
                    e => {
                        if (called) return;
                        called = true;
                        reject(e);
                    }
                );
            } else {
                resolve(x);
            }
        } catch (e) {
            if (called) return;
            called = true;
            reject(e);
        }
    } else {
        resolve(x);
    }
}

// 下面是使用 promises-aplus-tests 进行测试的代码
_promise.defer = _promise.deferred = function () {
    let dfd = {};
    dfd.promise = new _promise((resolve, reject) => {
        dfd.resolve = resolve;
        dfd.reject = reject;
    });
    return dfd;
};
module.exports = _promise;
/* ---------------------- 其他方法简单实现 ---------------------- */
class {
		static resolve(vlaue) {
	        if (value instanceof _promise) {
	            return value;
	        }
        	return new _promise(resolve => resolve(value));
    	}
    	static reject(reason) {
        	return new _promise((resolve, reject) => reject(reason));
    	}
	    static all(promises) {
	        return new _promise((resolve, reject) => {
	            let index = 0,
	                len = promises.length,
	                result = [];
	            for (const item of promises) {
	                _promise.resolve(item).then(
	                    res => {
	                        result[index++] = res;
	                        if (index === len) {
	                            resolve(result);
	                        }
	                    },
	                    err => reject(err)
	                );
	            }
	        });
	    }
	    static race(promises) {
	        return new _promise((resolve, reject) => {
	            for (const item of promises) {
	                _promise.resolve(item).then(
	                    res => resolve(res),
	                    err => reject(err)
	                );
	            }
	        });
	    }   
	 static allSettled(promises) {
        const promiseArr = Array.from(promises);
        return _Promise.all(
            promiseArr.map(p =>
                _Promise.resolve(p).then(
                    res => {
                        return { status: 'fulfilled', value: res };
                    },
                    error => {
                        return { status: 'rejected', reason: error };
                    }
                )
            )
        );
    }
}

参考

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yokiizx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值