模擬Promise的功能

模擬Promise的功能,  按照下面的步驟,一步一步

1. 新建是個構造函數

2. 傳入一個可執行函數 函數的入參第一個爲 fullFill函數 第二個爲 reject函數; 函數立即執行, 參數函數異步執行
3. 狀態一旦更改就不可以變更 只能 pending => fulfilled 或者 pending => rejected
4. then 的時候要處理入參的情況 successCallback 和failCallback 均可能爲非函數

  • 默認的 failCallback 一定要將異常拋出, 這樣下一個promise便可將其捕獲 異常冒泡的目的

5. then 中執行回調的時候要捕獲異常 將其傳給下一個promise

  • 如果promise狀態未變更 則將回調方法添加到對應隊列中
  • 如果promise狀態已經變更 需要異步處理成功或者失敗回調
  • 因爲可能出現 回調結果和當前then返回的Promise一致 從而導致死循環問題

6. catch只是then的一種特殊的寫法 方便理解和使用
7. finally 特點

  1. 不過resolve或者reject都會執行
  2. 回調沒有參數
  3. 返回一個Promise 且值可以穿透到下一個then或者catch

8. Promise.resolve, Promise.reject 根據其參數返回對應的值 或者狀態的Promise即可
9. Proise.all 特點

  1. 返回一個Promise
  2. 入參是數組 resolve的情況下出參也是數組 且結果順序和調用順序一致
  3. 所有的值或者promise都完成才能resolve 所有要計數
  4. 只要有一個爲reject 返回的Promise便reject

10. Proise.race 特點

  1. 返回一個Promise
  2. 入參是數組 那麼出參根據第一個成功或者失敗的參數來確定
  3. 只要有一個resolve 或者reject 便更改返回Promise的狀態

 

const PENDING = 'pending' //等待
const FULFILLED = 'fulfilled' //成功
const REJECTED = 'rejected' //失敗

const fulfilledCallback = [] //成功回調函數
const rejectedCallback = []  //失敗回調函數

class MyPromise {
   
    constructor (executor) {
        
        try{
            executor(this.resolve, this.reject)
        } catch (e){
            this.reject(e)
        }
    }

    status = PENDING//promise的狀態
    value = undefined//成功之後的值
    reason = undefined//失敗之後的值
    fulfilledCallback = [] //成功回調函數
    rejectedCallback = []  //失敗回調函數
    resolve = value => {
        //如果狀態不是等待, 阻止程序繼續往下執行
        if(this.status !== PENDING){
            return
        }
        this.status = FULFILLED
        this.value = value
        //判斷成功回調是否存在,如果存在, 調用
        // this.fulfilledCallback && this.fulfilledCallback(this.value)
        while(this.fulfilledCallback.length) this.fulfilledCallback.shift()()

    }
    reject = reason => {
        //如果狀態不是等待, 阻止程序繼續往下執行
        if(this.status !== PENDING){
            return
        }
        this.status = REJECTED
        this.reason = reason
        //判斷失敗回調是否存在,如果存在, 調用
        // this.rejectedCallback && this.rejectedCallback(this.reason)
        while(this.rejectedCallback.length) this.rejectedCallback.shift()()
    }
    then = (fulfilledCallback, rejectedCallback) => {
        fulfilledCallback = fulfilledCallback ? fulfilledCallback : value => value
        rejectedCallback = rejectedCallback ? rejectedCallback : reason => {throw reason}
        let promise2 = new MyPromise((resolve, reject) => {
            
            //判斷狀態
            if(this.status === FULFILLED){
                setTimeout(() => {
                    try {
                        //判斷x 傳過來的可能是promise,先查看promise返回的結果,在決定是用resolve還是reject,
                        //如果是普通值,直接調用resolve
                        let x = fulfilledCallback(this.value)
                        //外面加載完,才能獲取到promise2,用異步解決
                        resolvePromise(promise2,x,resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                    
                },0)
               
            }else if(this.status === REJECTED){
                
                setTimeout(() => {
                    try {
                        //判斷x 傳過來的可能是promise,先查看promise返回的結果,在決定是用resolve還是reject,
                        //如果是普通值,直接調用resolve
                        let x = rejectedCallback(this.reason)
                        //外面加載完,才能獲取到promise2,用異步解決
                        resolvePromise(promise2,x,resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                    
                },0)
            }else{
                //等待狀態
                this.fulfilledCallback.push(() => {
                    setTimeout(() => {
                        try {
                            //判斷x 傳過來的可能是promise,先查看promise返回的結果,在決定是用resolve還是reject,
                            //如果是普通值,直接調用resolve
                            let x = fulfilledCallback(this.value)
                            //外面加載完,才能獲取到promise2,用異步解決
                            resolvePromise(promise2,x,resolve, reject)
                        } catch (error) {
                            reject(error)
                        }
                        
                    },0)
                });
                this.rejectedCallback.push(() => {
                    setTimeout(() => {
                        try {
                            //判斷x 傳過來的可能是promise,先查看promise返回的結果,在決定是用resolve還是reject,
                            //如果是普通值,直接調用resolve
                            let x = rejectedCallback(this.reason)
                            //外面加載完,才能獲取到promise2,用異步解決
                            resolvePromise(promise2,x,resolve, reject)
                        } catch (error) {
                            reject(error)
                        }
                        
                    },0)
                });
            }
        })
        return promise2
    }

    static all (array) {
        let result= []
        let index = 0;

        return new MyPromise((resolve, reject) => {

            function addData (key, value) {
                result[key] = value
                index++
                if (index === array.length) {
                    resolve(result)
                }
            }

            for (let i = 0; i < array.length; i++) {
                
                if (array[i] instanceof MyPromise) {
                    //promise對象
                    array[i].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))

    }

    finally (callback) {
        return this.then(value => {
            return MyPromise.resolve(callback()).then(() => value)
        }, reason => {
            return MyPromise.resolve(callback()).then(() => {throw reason})
        })

    }

    catch (rejectedCallback) {
        return this.then(undefined, rejectedCallback)
    }

}

function resolvePromise(promise2,x,resolve, reject){

    if(x === promise2){
        return reject(new TypeError('啦啦啦啦'))
    }
    if(x instanceof MyPromise){
        //是promise
        //往下直接傳
        x.then(resolve,reject)
    }else{
        //普通值
        resolve(x)
    }
}

module.exports = MyPromise;

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章