https://s3-us-west-2.amazonaws.com/secure.notion-static.com/b82b9124-37dd-49cc-ac25-99cc4405633e/Untitled.png

手写Promise,全部测试通过!

promises-aplus-tests

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MPromise {
    constructor(ex) {
        this.state = PENDING;
        this.value = undefined;
        this.reason = undefined;
        this.rejCallbacks = [];
        this.resCallbacks = [];
        const resolve = (val) => {
            if (this.state === PENDING) {
                this.state = FULFILLED;
                this.value = val;
                this.resCallbacks.map(fn => fn());
            }
        }
        const reject = (val) => {
            if (this.state === PENDING) {
                this.state = REJECTED;
                this.value = val;
                this.rejCallbacks.map(fn => fn());
            }
        }

        try {
            ex(resolve, reject)
        } catch (e) {
            reject(e)
        }
    }
    then(OnFullfill, OnReject) {
        /**
         * 如果传入非函数参数,将参数变成函数
         */
        OnFullfill = typeof OnFullfill === 'function' ? OnFullfill : val => val;
        OnReject = typeof OnReject === 'function' ? OnReject : val => { throw val }

        /**
         * then是异步执行的,then的所有执行会放到下一次事件循环,其中x是上一次then的返回值
         */
        let promise2 = new MPromise((resolve, reject) => {
            if (this.state === FULFILLED) {
                setTimeout(() => {
                    try {
                        let x = OnFullfill(this.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e)
                    }
                })
            }

            if (this.state === REJECTED) {
                setTimeout(() => {
                    try {
                        let x = OnReject(this.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (e) {
                        reject(e)
                    }
                })
            }

            if (this.state === PENDING) {
                this.resCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            let x = OnFullfill(this.value);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            reject(e);
                        }
                    })
                });

                this.rejCallbacks.push(() => {
                    setTimeout(() => {
                        try {
                            let x = OnReject(this.value);
                            resolvePromise(promise2, x, resolve, reject);
                        } catch (e) {
                            reject(e)
                        }
                    })
                });
            }
        })

        return promise2;
    }
}
function resolvePromise(promise2, x, resolve, reject) {
    /**
     * 循环引用,p1=new Promise(...) ; p2 = p1.then(r=>{return p2})
     */
    if (promise2 === x) {
        reject(new TypeError('Chaining cycle'))
    }
    /**
     * 解决then返回promise    resolve({then:...})  resolve(new Promise(function(res,rej)=>{...}))
     */
    if (x && typeof x === 'object' || typeof x === 'function') {
        let used;
        try {
            /**
             * 难点,解决thenable方法的处理
             */
            let then = x.then
            /**
             * 当上一次then传递过来的then,used变量用于确保回调时两种状态只执行一种
             */
            if (typeof then === 'function') {
                then.call(x, (y) => {
                    /**
                     * y是resolve的值
                     * new Promise(function(resovle,reject){
                     *      resolve(1)
                     * }).then(x=>{
                     *  return(new Promise(...))
                     * })
                     * 下面这个then call的是120行的Promise的then
                     * 解释:如果120行return的是一个Promise对象,包含了then方法,
                     * 在调用then时,会调用120行的Promise的then方法,它的then第一个参数是这里的y,
                     * 即是它resolve的值,resolve的结果最终会传给顶层的resolve解决
                     * 这里把y和promise2传递下去执行
                     * 下面的then不是120行的then,但是是120行then调用后resolve的结果
                     * .then(xpromise=>{
                     *  console.log(xpromise) //是上一个Promise resolve的值,不是一个Promise
                     * })
                     */
                    if (used) return;
                    used = true;
                    resolvePromise(promise2, y, resolve, reject);
                }, (r) => {
                    if (used) return;
                    used = true;
                    reject(r);
                })
            }
            /**
             * then不是函数,直接resolve x
             */
            else {
                resolve(x)
            }
        } catch (e) {
            if (used) return;
            used = true
            reject(e)
        }
    } else {
        resolve(x)
    }
}

MPromise.defer = MPromise.deferred = function () {
    let dfd = {};
    dfd.promise = new MPromise((resolve, reject) => {
        dfd.resolve = resolve;
        dfd.reject = reject;
    });
    return dfd;
}

module.exports = MPromise;