手写Promise源码

175 阅读3分钟
/*
    1、Promise就是一个类,在执行这个类的时候,需要传递一个执行器进去,执行器就会立即执行
    2、Promise中有三种状态,分别是成功fulfilled、失败rejected、等待pending
       pending->fulfilled
       pending->rejected
       一旦状态确定就不会改变
    3、resolve和reject函数是用来更改状态的
       resolve:fulfilled
       reject:rejected
    4、then方法内部做的事情就判断状态
       如果状态是成功,调用成功的回调函数
       如果状态是失败,调用失败的回调函数
       then方法是被定义在原型对象中的
    5、then成功回调有一个参数,表示成功之后的值,then失败回调有一个参数,表示失败后的原因
    6、同一个promise对象下面的then方法是可以被调用多次的
    7、then方法可以被链式调用,后面的then方法的回调函数拿到值的是上一个then方法的回调函数的返回值
    8、all、finally方法编写
*/

const PENDING = 'pending'
const FULFILLED = 'fulfiled'
const REJECTED = 'rejected'
class MyPromise{
    constructor(executor){
        //捕获执行器错误
        try{
            executor(this.resolve,this.reject)
        }catch(e){
            this.reject(e)
        }
    }
    //Promise状态
    status = PENDING
    //成功之后的值
    value = undefined
    //失败后的原因
    reason = undefined
    //成功回调
    successCallback = [];
    //失败回调
    failCallback = [];
    resolve = value => {
        //如果状态不是等待,阻止程序向下执行
        if(this.status !== PENDING) return
        //将状态更改为成功
        this.status = FULFILLED
        //保存成功之后的值
        this.value = value
        // 判断成功回调是否存在 如果存在 调用
        // this.successCallback && this.successCallback(this.value);
        while(this.successCallback.length)
            this.successCallback.shift()(this.value)
    }
    reject = reason => {
        //如果状态不是等待,阻止程序向下执行
        if(this.status !== PENDING) return
        //将状态更改为失败
        this.status = REJECTED
        //保存失败后的原因
        this.reason = reason
        // 判断失败回调是否存在 如果存在 调用
        // this.failCallback&& this.failCallback(this.reason);
        while(this.failCallback.length)
            this.failCallback.shift()(this.reason)
    }
    then(successCallback,failCallback){
        //参数可选
        successCallback = successCallback ? successCallback : value => value
        failCallback = failCallback ? failCallback: reason=> {throw reason}
        let promise1 = new MyPromise((resolve,reject)=>{
            //判断状态
            if(this.status === FULFILLED){
                //将同步代码转成异步代码
                setTimeout(()=>{
                    try{
                        let x = successCallback(this.value)
                        // 判断 x 的值是普通值还是promise对象
                        // 如果是普通值 直接调用resolve 
                        // 如果是promise对象 查看promsie对象返回的结果 
                        // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
                        resolvePromise(promise1,x,resolve,reject)
                    }catch(e){
                        reject(e)
                    }
                },0)
            }else if(this.status === REJECTED ){
                //将同步代码转成异步代码
                setTimeout(()=>{
                    try{
                        let x = failCallback(this.reason)
                        // 判断 x 的值是普通值还是promise对象
                        // 如果是普通值 直接调用resolve 
                        // 如果是promise对象 查看promsie对象返回的结果 
                        // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
                        resolvePromise(promise1,x,resolve,reject)
                    }catch(e){
                        reject(e)
                    }
                },0)
            }else{
                // 等待
                // 将成功回调和失败回调存储起来
                this.successCallback.push(()=>{
                    setTimeout(()=>{
                        try{
                            let x = successCallback(this.value)
                            // 判断 x 的值是普通值还是promise对象
                            // 如果是普通值 直接调用resolve 
                            // 如果是promise对象 查看promsie对象返回的结果 
                            // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
                            resolvePromise(promise1,x,resolve,reject)
                        }catch(e){
                            reject(e)
                        }
                    },0)
                })
                this.failCallback.push(()=>{
                    //将同步代码转成异步代码
                    setTimeout(()=>{
                        try{
                            let x = failCallback(this.reason)
                            // 判断 x 的值是普通值还是promise对象
                            // 如果是普通值 直接调用resolve 
                            // 如果是promise对象 查看promsie对象返回的结果 
                            // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
                            resolvePromise(promise1,x,resolve,reject)
                        }catch(e){
                            reject(e)
                       }
                    },0)
                })
            }
        })
        return promise1
    }
    /*
        finally方法特点:
            无论当前Promise对象最终是成功还是失败,finally方法都会被执行;
            在finally方法后面可以链式调用then方法来拿到当前Promise对象返回的结果
    */
    finally(callback){
        return this.then(value=>{
            //成功的回调
            return MyPromise.resolve(callback()).then(()=>value)
        },reason=>{
            //失败的回调
            return MyPromise.resolve(callback()).then(()=>{throw reason})
        })
    }
    //catch方法处理当前Promise对象最终状态为失败的情况
    catch (failCallback) {
        return this.then(undefined, failCallback)
    }
    static all(array){
        let result = []
        let index = 0
        function addData (key, value) {
            result[key] = value;
            index++;
            if (index === array.length) {
                  resolve(result);
            }
        }
        return new MyPromise((resolve,reject)=>{
            for(let i = 0;i < array.length;i++){
                let current = array[i]
                if(current instanceof MyPromise){
                    //Promise对象
                    current.then(value => addData(i, value), reason => reject(reason))
                }else{
                    //普通值
                    addData(i, array[i]);
                }
            }
        })
    }
    static resolve(value){
        if(value instanceof MyPromise)
            return value
        return new MyPromise(resolve => resolve(value))
    }
}
//链式调用
function resolvePromise (promise1, x, resolve, reject) {
    if(promise1 === x){
        reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
    }
    if (x instanceof MyPromise) {
        // promise 对象
        x.then(resolve, reject);
    } else {
        // 普通值
        resolve(x);
    }
}

module.exports = MyPromise