手写一个简易的Promise

63 阅读1分钟
const PENDING='pending';
const FULFILLED='fulfilled'
const REJECTED='rejected'

class MyPromise{
    constructor(executer){
        try{
            executer(this.resolve,this.reject)
        }
        catch(e){
            this.reject(e)
        }
    }
    value=undefined
    reason=undefined
    status=PENDING
    successCallbacks=[]
    failCallbacks=[]
    
    static resolve(v){
        if(v instanceof MyPromise){
            return v;
        }
        return new MyPromise(resolve=>resolve(v))
    }
    resolve=v=>{
        if(this.status!==PENDING)return;
         //调用的时候,如果状态不是等待态,就把收集的success函数队列依次执行
        this.value=v;
        this.status=FULFILLED;
        while(this.successCallbacks.length){
            successCallbacks.shift()();
        }
    }
    reject=e=>{
        if(this.status!==PENDING)return;
        this.reason=e;
        this.status=REJECTED;
        while(this.failCallbacks.length){
            failCallbacks.shift()();
        }
    }
    then(successCallback,failCallback){
        successCallback=typeof successCallback==='function'?successCallback:v=>v;
        failCallback=typeof failCallback==='funtion'?failCallback:e=>{throw e};
        const subPromise = new MyPromise((resolve,reject)=>{
            switch(this.status){
                //调用then的时候,如果promise的状态已经改变了,则直接开启微任务执行回调
                //然后交给resolvePromise判断要resolve还是reject
                case FULFILLED:{
                   queueMicrotask(()=>{
                        try{
                            const x=successCallback(this.value);
                            resolvePromise(subPromise,x,resolve,reject);
                        }
                        catch(e){
                            reject(e)
                        }
                    })
                    break;
                }
                case REJECTED:{
                    queueMicrotask(()=>{
                        try{
                            const x=failCallback(this.reason);
                            resolvePromise(subPromise,x,resolve,reject);
                        }
                        catch(e){
                            reject(e)
                        }
                    })
                    break;
                }
                //调用then的时候,如果是还没改变状态,收集封装好的微任务函数
                case PENDING:{
                  successCallbacks.push(()=>{
                        queueMicrotask(()=>{
                            try{
                                const x=successCallback(this.value);
                                resolvePromise(subPromise,x,resolve,reject);
                            }
                            catch(e){
                                reject(e)
                            }
                        })
                    })
                    failCallbacks.push(()=>{
                        queueMicrotask(()=>{
                            try{
                                const x=failCallback(this.reason);
                                resolvePromise(subPromise,x,resolve,reject);
                            }
                            catch(e){
                                reject(e)
                            }
                        })
                    })
                    break;
                }
            }
        })
        return subPromise;
    }
    catch(onRejected){
        this.then(null,onRejected)
    }
    finally(callback){
        return this.then(
            v=>MyPromise.resolve(callback()).then(()=>v),
            e=>MyPromise.resolve(callback()).then(()=>{throw e}),
        )
    }
}
function resolvePromise(subPromise,x,resolve,reject){
    if(subPromise===x){
        reject(new typeError('Chaining caycle detected for promise #<Promise>'))
    }
    else if(x instanceof MyPromise){
        return x
    }
    else {
        reslove(x)
    }
}