美文网首页
手写实现 Promise/A+ 标准

手写实现 Promise/A+ 标准

作者: 越前君 | 来源:发表于2020-01-31 16:53 被阅读0次

    本文仅作为个人记录,文中可能存在不严谨的地方。

    要了解更多可以看下这两篇文章:
    史上最易读懂的 Promise/A+ 完全实现
    promise/A+规范翻译以及手写实现

    Promise/A+ 的标准有哪些?

    1. 只有一个 then 方法,没有 catch、race、all 等方法。

    2. then 返回一个新的 Promise。

    3. 不同的 Promise 的实现需要相互调用。

    4. Promise 的状态有 pending、fullfilled、rejected 三种。初始状态是 pending ,可以由 pending 转化为 fullfilled 或者 rejected。一旦状态确定之后,不能再被改变。

    5. 更具体的官方标准,看这里

    下面上代码

    function MyPromise(executor) {
        const _this = this;
        // 状态
        _this.status = 'pending';
        // resolve 值
        _this.value = null;
        // reject 原因
        _this.reason = null;
        // resolve、reject 函数
        _this.onFullfilled = [];
        _this.onRejected = [];
    
    
        function resolve(value) {
            if (value instanceof MyPromise) {
                return value.then(resolve, reject);
            }
    
            // 其实这里采用 setTimeout 方式实现异步执行 onFullfilled/onRejected 不太符合 Event Loop 机制。下面 reject 同理。
            setTimeout(() => {
                // 只有状态为 pending 才能被改变
                if (_this.status == 'pending') {
                    _this.value = value;
                    _this.status = 'resolved';
                    _this.onFullfilled.forEach(currentValue => currentValue(value));
                }
            }, 0);
        }
    
        function reject(reason) {
            setTimeout(() => {
                // 只有状态为 pending 才能被改变
                if (_this.status == 'pending') {
                    _this.reason = reason;
                    _this.status = 'rejected';
                    _this.onRejected.forEach(currentValue => currentValue(reason));
                }
            }, 0);
        }
    
        // 注意:若执行过程出现异常,则捕获异常并执行 reject 函数。
        try {
            executor(resolve, reject)
        } catch (e) {
            reject(e);
        }
    }
    
    function resolvePromise(promise2, x, resolve, reject) {
        let then;
        let thenCallorThrow = false;
    
        if (promise2 === x) {
            return reject(new TypeError('same Promise!'))
        }
    
        if (x instanceof MyPromise) {
            if (x.status === 'pending') {
                x.then(value => {
                    resolvePromise(promise2, value, resolve, reject)
                }, reject)
            } else {
                x.then(resolve, reject)
            }
            return
        }
    
        if ((x !== null) && ((typeof x === 'object') || (typeof x === 'function'))) {
            try {
                then = x.then;
                if (typeof then === 'function') {
                    then.call(x, res => {
                        if (thenCallorThrow) return;
                        thenCallorThrow = true;
                        return resolvePromise(promise2, res, resolve, reject);
                    }, err => {
                        if (thenCallorThrow) return;
                        thenCallorThrow = true;
                        return reject(err)
                    })
                } else {
                    resolve(x);
                }
            } catch (e) {
                if (thenCallorThrow) return;
                thenCallorThrow = true;
                return reject(e)
            }
        } else {
            return resolve(x)
        }
    }
    
    MyPromise.prototype.then = function (onFullfilled, onRejected) {
        const _this = this;
        let promise2;   // promise.then() 返回一个 promise 对象
    
        // Promise 值的穿透处理:
        // 场景如: new Promise(resolve => resolve('abc')).then().catch().then(res => {console.log('print abc')})
        onFullfilled = typeof onFullfilled === 'function' ? onFullfilled : val => val;
        onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };
    
        switch (_this.status) {
            case 'pending':
                promise2 = new MyPromise((resolve, reject) => {
                    _this.onFullfilled.push(value => {
                        try {
                            let x = onFullfilled(value);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            reject(e)
                        }
                    });
                    _this.onRejected.push(reason => {
                        try {
                            let x = onRejected(reason);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            reject(e)
                        }
                    });
                })
            case 'resolved':
                promise2 = new MyPromise((resolve, reject) => {
                    setTimeout(() => {
                        try {
                            let x = onFullfilled(_this.value);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            reject(e)
                        }
                    });
                })
            case 'rejected':
                promise2 = new MyPromise((resolve, reject) => {
                    setTimeout(() => {
                        try {
                            let x = onRejected(_this.reason);
                            resolvePromise(promise2, x, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    });
                })
            default:
                break;
        }
    
        return promise2;
    }
    
    // Promise 标准里面没有 catch、race、all 等方法,只有一个 then 方法
    MyPromise.prototype.catch = function (onRejected) {
        return this.then(null, onRejected)
    }
    
    
    new MyPromise((resolve, reject) => {
        resolve('right');
    }).then(res => {
        console.log(res)
    }, err => {
        console.warn(err)
    })
    

    相关文章

      网友评论

          本文标题:手写实现 Promise/A+ 标准

          本文链接:https://www.haomeiwen.com/subject/dywgthtx.html