自定義promise

promise的詳細(xì)介紹-來源博客(YK菌

1、自定義Promise 函數(shù)版本 IIFE
(function (window) {
    const PENDING = "pending"
    const RESOLVED = "resolved"
    const REJECTED = "rejected"
    /**promise 構(gòu)造函數(shù)   excutor執(zhí)行器函數(shù)*/
    function Promise(excutor) {
        //給promise對(duì)象指定status屬性,初始值為pending
        this.status = PENDING
        //給promise對(duì)象指定一個(gè)用于存儲(chǔ)結(jié)果數(shù)據(jù)的屬性
        this.data = undefined;
        //每個(gè)元素的結(jié)構(gòu) {onResolved(){},onrejected(){}}
        this.callbacks = []
        let self = this;
        function resolve(value) {
            //狀態(tài)更改過以后不再執(zhí)行
            if (self.status !== PENDING) {
                return
            }
            //更改狀態(tài)
            self.status = RESOLVED
            //保存value數(shù)據(jù)
            self.data = value
            //如果有待執(zhí)行cakkback函數(shù),立即異步執(zhí)行回調(diào)函數(shù)
            if (self.callbacks.length > 0) {
                setTimeout(() => {//放入隊(duì)列中執(zhí)行所有成功的回調(diào)
                    self.callbacks.forEach(callbacksObj => {
                        callbacksObj.onResolved(value)
                    });
                })

            }
        }
        function reject(reason) {
            //狀態(tài)更改過以后不再執(zhí)行
            if (self.status !== PENDING) {
                return
            }
            //更改狀態(tài)
            self.status = REJECTED
            //保存value數(shù)據(jù)
            self.data = reason
            //如果有待執(zhí)行cakkback函數(shù),立即異步執(zhí)行回調(diào)函數(shù)
            if (self.callbacks.length > 0) {
                setTimeout(() => {//放入隊(duì)列中執(zhí)行所有失敗的回調(diào)
                    self.callbacks.forEach(callbacksObj => {
                        callbacksObj.onRejected(reason)
                    });
                })

            }
        }
        try {
            //立即同步執(zhí)行excutor
            excutor(resolve, reject)
        } catch (error) {//如果執(zhí)行器拋出異常
            reject(error)
        }

    }

    /**原型上的then*/
    Promise.prototype.then = function (onResolved, onRejected) {
        let self = this;
        onResolved = typeof onResolved === 'function' ? onResolved : value => value
        //實(shí)現(xiàn)異常穿透
        onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }

        //返回一個(gè)新的promise對(duì)象
        return new Promise((resolve, reject) => {
            //調(diào)用指定回調(diào)函數(shù)處理,根據(jù)執(zhí)行結(jié)果,改變r(jià)eturn的promise狀態(tài)
            function handle(fn) {
                /**
                     1、如果執(zhí)行拋出異常 return的promise就會(huì)失敗,reason就是error
                     2、如果回調(diào)函數(shù)不是promise,return的promise就會(huì)成功,value就是返回值
                     3、如果回調(diào)函數(shù)返回的是promise,return的promise結(jié)果就是這個(gè)promise 的結(jié)果
                    */
                try {
                    let result = fn(self.data)
                    //    3、如果回調(diào)函數(shù)返回的是promise,return的promise結(jié)果就是這個(gè)promise 的結(jié)果
                    if (result instanceof Promise) {
                        result.then(resolve, reject)
                        //等價(jià)于
                        // result.then(
                        //     value => {resolve(value)},
                        //     reason => {reject(reason)}
                        // )
                    } else {
                        // 2、如果回調(diào)函數(shù)不是promise,return的promise就會(huì)成功,value就是返回值
                        resolve(result)
                    }
                } catch (err) {
                    reject(err)
                }
            }
            //如果狀態(tài)還沒有被更改此時(shí)緩存回調(diào)函數(shù)
            if (self.status === RESOLVED) {
                //如果是狀態(tài)已經(jīng)更改過了,回調(diào)函數(shù)放入隊(duì)列中,并改變promise的狀態(tài)
                setTimeout(() => {
                    handle(onResolved)
                })
            } else if (self.status === REJECTED) {//rejected
                //如果是狀態(tài)已經(jīng)更改過了,回調(diào)函數(shù)放入隊(duì)列中
                setTimeout(() => {
                    handle(onRejected)
                })
            } else {
                //當(dāng)前還是pending狀態(tài),保存回調(diào)函數(shù),
                self.callbacks.push({
                    onResolved() {
                        handle(onResolved)
                    },
                    onRejected() {
                        handle(onRejected)
                    }
                })
            }
        })
    }
    /**原型上的catch*/
    Promise.prototype.catch = function (onRejected) {
        return this.then(undefined, onRejected)

    }
    /**函數(shù)對(duì)象的方法 resolve*/
    Promise.resolve = function (value) {
        //返回一個(gè)成功或者失敗的promise
        return new Promise((resolve, reject) => {
            try {
                //    3、如果回調(diào)函數(shù)返回的是promise,return的promise結(jié)果就是這個(gè)promise 的結(jié)果
                if (value instanceof Promise) {
                    value.then(resolve, reject)
                } else {
                    // 2、如果回調(diào)函數(shù)不是promise,return的promise就會(huì)成功,value就是返回值
                    resolve(value)
                }
            } catch (err) {
                reject(err)
            }
        })
    }
    /**函數(shù)對(duì)象的方法 reject*/
    Promise.reject = function (reason) {
        return new Promise((resolve, reject) => {
            reject(reason)
        })
    }
    /**函數(shù)對(duì)象的方法 all*/
    Promise.all = function (promises) {
        let list = new Array(promises.length)
        let resolvedCount = 0
        return new Promise((resolve, reject) => {
            //遍歷獲取所有promise的結(jié)果
            promises.forEach((p, index) => {
                Promise.resolve(p).then(
                    value => {
                        list[index] = value
                        resolvedCount++
                        //如果全部成功,將狀態(tài)置為成功
                        if (resolvedCount === promises.length) {
                            resolve(list)
                        }
                    },
                    reason => {//只要有一個(gè)失敗了,return的promise就失敗了
                        reject(reason)
                    }
                )
            })
        })


    }
    /**函數(shù)對(duì)象的方法 race*/
    Promise.race = function (promises) {
        let resolvedCount = 0
        return new Promise((resolve, reject) => {
            //遍歷獲取所有promise的結(jié)果
            promises.forEach((p, index) => {
                Promise.resolve(p).then(
                    value => {
                        //如果有一個(gè)成功,將狀態(tài)置為成功if (resolvedCount === promises.length) {
                        resolve(value)
                    },
                    reason => {//只要有一個(gè)失敗了,return的promise就失敗了
                        reject(reason)
                    }
                )
            })
        })
    }
    /**自定義函數(shù)對(duì)象的方法 resolveDelay 返回一個(gè)函數(shù)在指定的時(shí)間后才確定結(jié)果*/
    Promise.resolveDelay = function (value,time=1000) {

        //返回一個(gè)成功或者失敗的promise
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                try {
                    //    3、如果回調(diào)函數(shù)返回的是promise,return的promise結(jié)果就是這個(gè)promise 的結(jié)果
                    if (value instanceof Promise) {
                        value.then(resolve, reject)
                    } else {
                        // 2、如果回調(diào)函數(shù)不是promise,return的promise就會(huì)成功,value就是返回值
                        resolve(value)
                    }
                } catch (err) {
                    reject(err)
                }
            }, time)
        })
    }
    /**自定義函數(shù)對(duì)象的方法 rejectDelay 返回一個(gè)函數(shù)在指定的時(shí)間后才失敗*/
    Promise.rejectDelay = function (value,time=1000) {
        setTimeout(() => {
            return new Promise((resolve, reject) => {
                reject(reason)
            })
        }, time)

    }
    window.Promise = Promise
})(window)
2、自定義Promise 類版本

(function (window) {
    const PENDING = "pending"
    const RESOLVED = "resolved"
    const REJECTED = "rejected"
    class Promise {
        constructor(excutor) {
            //給promise對(duì)象指定status屬性,初始值為pending
            this.status = PENDING
            //給promise對(duì)象指定一個(gè)用于存儲(chǔ)結(jié)果數(shù)據(jù)的屬性
            this.data = undefined;
            //每個(gè)元素的結(jié)構(gòu) {onResolved(){},onrejected(){}}
            this.callbacks = []
            let self = this;
            function resolve(value) {
                //狀態(tài)更改過以后不再執(zhí)行
                if (self.status !== PENDING) {
                    return
                }
                //更改狀態(tài)
                self.status = RESOLVED
                //保存value數(shù)據(jù)
                self.data = value
                //如果有待執(zhí)行cakkback函數(shù),立即異步執(zhí)行回調(diào)函數(shù)
                if (self.callbacks.length > 0) {
                    setTimeout(() => {//放入隊(duì)列中執(zhí)行所有成功的回調(diào)
                        self.callbacks.forEach(callbacksObj => {
                            callbacksObj.onResolved(value)
                        });
                    })

                }
            }
            function reject(reason) {
                //狀態(tài)更改過以后不再執(zhí)行
                if (self.status !== PENDING) {
                    return
                }
                //更改狀態(tài)
                self.status = REJECTED
                //保存value數(shù)據(jù)
                self.data = reason
                //如果有待執(zhí)行cakkback函數(shù),立即異步執(zhí)行回調(diào)函數(shù)
                if (self.callbacks.length > 0) {
                    setTimeout(() => {//放入隊(duì)列中執(zhí)行所有失敗的回調(diào)
                        self.callbacks.forEach(callbacksObj => {
                            callbacksObj.onRejected(reason)
                        });
                    })

                }
            }
            try {
                //立即同步執(zhí)行excutor
                excutor(resolve, reject)
            } catch (error) {//如果執(zhí)行器拋出異常
                reject(error)
            }
        }
        /**原型上的then*/
        then(onResolved, onRejected) {
            let self = this;
            onResolved = typeof onResolved === 'function' ? onResolved : value => value
            //實(shí)現(xiàn)異常穿透
            onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }

            //返回一個(gè)新的promise對(duì)象
            return new Promise((resolve, reject) => {
                //調(diào)用指定回調(diào)函數(shù)處理,根據(jù)執(zhí)行結(jié)果,改變r(jià)eturn的promise狀態(tài)
                function handle(fn) {
                    /**
                         1、如果執(zhí)行拋出異常 return的promise就會(huì)失敗,reason就是error
                         2、如果回調(diào)函數(shù)不是promise,return的promise就會(huì)成功,value就是返回值
                         3、如果回調(diào)函數(shù)返回的是promise,return的promise結(jié)果就是這個(gè)promise 的結(jié)果
                        */
                    try {
                        let result = fn(self.data)
                        //    3、如果回調(diào)函數(shù)返回的是promise,return的promise結(jié)果就是這個(gè)promise 的結(jié)果
                        if (result instanceof Promise) {
                            result.then(resolve, reject)
                            //等價(jià)于
                            // result.then(
                            //     value => {resolve(value)},
                            //     reason => {reject(reason)}
                            // )
                        } else {
                            // 2、如果回調(diào)函數(shù)不是promise,return的promise就會(huì)成功,value就是返回值
                            resolve(result)
                        }
                    } catch (err) {
                        reject(err)
                    }
                }
                //如果狀態(tài)還沒有被更改此時(shí)緩存回調(diào)函數(shù)
                if (self.status === RESOLVED) {
                    //如果是狀態(tài)已經(jīng)更改過了,回調(diào)函數(shù)放入隊(duì)列中,并改變promise的狀態(tài)
                    setTimeout(() => {
                        handle(onResolved)
                    })
                } else if (self.status === REJECTED) {//rejected
                    //如果是狀態(tài)已經(jīng)更改過了,回調(diào)函數(shù)放入隊(duì)列中
                    setTimeout(() => {
                        handle(onRejected)
                    })
                } else {
                    //當(dāng)前還是pending狀態(tài),保存回調(diào)函數(shù),
                    self.callbacks.push({
                        onResolved() {
                            handle(onResolved)
                        },
                        onRejected() {
                            handle(onRejected)
                        }
                    })
                }
            })
        }
        /**原型上的catch*/
        catch(onRejected) {
            return this.then(undefined, onRejected)

        }
        /**函數(shù)對(duì)象的方法 resolve*/
        static resolve = function (value) {
            //返回一個(gè)成功或者失敗的promise
            return new Promise((resolve, reject) => {
                try {
                    //    3、如果回調(diào)函數(shù)返回的是promise,return的promise結(jié)果就是這個(gè)promise 的結(jié)果
                    if (value instanceof Promise) {
                        value.then(resolve, reject)
                    } else {
                        // 2、如果回調(diào)函數(shù)不是promise,return的promise就會(huì)成功,value就是返回值
                        resolve(value)
                    }
                } catch (err) {
                    reject(err)
                }
            })
        }
        /**函數(shù)對(duì)象的方法 reject*/
        static reject = function (reason) {
            return new Promise((resolve, reject) => {
                reject(reason)
            })
        }
        /**函數(shù)對(duì)象的方法 all*/
        static all = function (promises) {
            let list = new Array(promises.length)
            let resolvedCount = 0
            return new Promise((resolve, reject) => {
                //遍歷獲取所有promise的結(jié)果
                promises.forEach((p, index) => {
                    Promise.resolve(p).then(
                        value => {
                            list[index] = value
                            resolvedCount++
                            //如果全部成功,將狀態(tài)置為成功
                            if (resolvedCount === promises.length) {
                                resolve(list)
                            }
                        },
                        reason => {//只要有一個(gè)失敗了,return的promise就失敗了
                            reject(reason)
                        }
                    )
                })
            })


        }
        /**函數(shù)對(duì)象的方法 race*/
        static race = function (promises) {
            let resolvedCount = 0
            return new Promise((resolve, reject) => {
                //遍歷獲取所有promise的結(jié)果
                promises.forEach((p, index) => {
                    Promise.resolve(p).then(
                        value => {
                            //如果有一個(gè)成功,將狀態(tài)置為成功if (resolvedCount === promises.length) {
                            resolve(value)
                        },
                        reason => {//只要有一個(gè)失敗了,return的promise就失敗了
                            reject(reason)
                        }
                    )
                })
            })
        }
        /**自定義函數(shù)對(duì)象的方法 resolveDelay 返回一個(gè)函數(shù)在指定的時(shí)間后才確定結(jié)果*/
        static resolveDelay = function (value, time = 1000) {
            //返回一個(gè)成功或者失敗的promise
            return new Promise((resolve, reject) => {
                setTimeout(() => {
                    try {
                        //    3、如果回調(diào)函數(shù)返回的是promise,return的promise結(jié)果就是這個(gè)promise 的結(jié)果
                        if (value instanceof Promise) {
                            value.then(resolve, reject)
                        } else {
                            // 2、如果回調(diào)函數(shù)不是promise,return的promise就會(huì)成功,value就是返回值
                            resolve(value)
                        }
                    } catch (err) {
                        reject(err)
                    }
                }, time)
            })
        }
        /**自定義函數(shù)對(duì)象的方法 rejectDelay 返回一個(gè)函數(shù)在指定的時(shí)間后才失敗*/
        static ejectDelay = function (value, time = 1000) {
            setTimeout(() => {
                return new Promise((resolve, reject) => {
                    reject(reason)
                })
            }, time)

        }

    }
    window.Promise = Promise
})(window)
3、promise.all中,其中一個(gè)promise出錯(cuò),如何確保執(zhí)行到最后
       let p1 = new Promise((resolve, reject) => {
          resolve("p1");
        });
        let p2 = new Promise((resolve, reject) => {
          resolve("p2");
        });
        let p3 = new Promise((resolve, reject) => {
          reject("p3");
        });
        Promise.all([p1, p2, p3])
          .then((res) => {
            console.log("res:", res);
          })
          .catch((err) => {
            console.log("err:", err);
          });
     //執(zhí)行結(jié)果為   err: p3
     //改寫一下,主動(dòng)去獲取報(bào)錯(cuò),然后自定義出錯(cuò)后的返回值,例子中如果使用null作為返回值的話
        Promise.all([p1, p2, p3].map((p) => p.catch((e) => 出錯(cuò)后的返回值)))
          .then((res) => {
            console.log("res:", res);
          })
          .catch((err) => {
            console.log("err:", err);
          });
      //執(zhí)行結(jié)果為 res:  ['p1', 'p2', null]
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容