特皮團隊:一年菜鳥實現Promise全部方法

從零手寫Promise完整版

  • 隨着前端技術的不斷髮展,用戶對界面的要求也在不斷提升,如今的前端再也不是以前的html+css, 而是html+css+js,可是想學好js首先要知道js的核心在於異步,說到異步大部分人第一時間會想到Promise
  • 那麼接下來咱們就來學習一下Promise是如何實現的吧。
  • 首先咱們回顧一下Promise的基本使用
const p = new Promise((resolve,reject)=>{
    resolve('返回成功的值')
    reject('返回失敗的值')
})

p.then(value=>{
    console.log(value) // 返回成功的值
})
  1. new Promise構造函數內的回調數是同步執行的
  2. then的回調函數,是異步執行的
  3. 調用resolve/reject後,狀態已定,狀態不能再改變
  4. .then每次返回的都是新的Promise
  5. Promise能夠嵌套

接着咱們從零開始來實現一下Promise

  • 先來實現明確一下基本的結構
(function(window){
    // 定義MyPromise構造函數
    function MyPromise(executor){

        function resolve(value){

        }
        function reject(reason){

        }
        executor(resolve,reject)
    }
    // MyPromise原型鏈上存在then方法
    MyPromise.prototype.then = function(onResolved,onRejected){

    }
    //MyPromise原型鏈上存在catch方法
    MyPromise.prototype.catch = function(onRejected){

    }

    //MyPromise實例對象上存在resolve方法
    MyPromise.resolve = function(value){

    }

    //MyPromise實例對象上存在reject方法
    MyPromise.reject = function(reason){

    }

    //MyPromise實例對象上存在all方法
    MyPromise.all = function(promises){

    }

    //MyPromise實例對象上存在race方法
    MyPromise.race = function(promises){
        
    }

    window.MyPromise = MyPromise;
})(window)
  • 明確來了基本的結構後,接下里咱們來看看MyPromise構造函數內須要作什麼
  • 1.定義Promise的初始狀態、初始值、存放待執行異步函數的數組
(function(window){
    const PENDDING = 'pendding';
    const FULFILLED = 'fulfilled';
    const REJECTED = 'rejected';
    function MyPromise(executor){
        const self = this;
        self.status = PENDDING; //初始狀態
        self.data = undefined; // 初始值
        self.callbacks = []; // 待執行異步回調函數的數組
    
        function resolve(value){
        }
        function reject(reason){
        }
        executor(resolve,reject)
    }
    window.MyPromise = MyPromise;
})(window)
    1. 根據Promise狀態的不一樣,進行修,賦值,以及當即執行異步回調
(function (window) {
    const PENDDING = 'pendding';
    const FULFILLED = 'fulfilled';
    const REJECTED = 'rejected';
    // 定義MyPromise
    function MyPromise(executor) {
        const self = this;
        self.status = PENDDING;
        self.data = undefined;
        self.callbacks = [];

        function resolve(value) {
            self.status = FULFILLED;
            self.data = value;
            // 當即執行異步回調函數
            setTimeout(() => {
                self.callbacks.forEach(callbacksObj => {
                    callbacksObj.onResolved(value);
                })
            })
        }

        function reject(reason) {
            self.status = REJECTED;
            self.data = reason;
            setTimeout(() => {
                self.callbacks.forEach(callbacksObj => {
                    callbacksObj.onRejected(reason);
                })
            })
        }
        executor(resolve, reject)
    }
    window.MyPromise = MyPromise;
    1. 別忘了Promise 的狀態一旦改變就不能再修改了,因此在resolve/reject函數內須要加一個判斷
(function (window) {
    const PENDDING = 'pendding';
    const FULFILLED = 'fulfilled';
    const REJECTED = 'rejected';
    // 定義MyPromise
    function MyPromise(executor) {
        const self = this;
        self.status = PENDDING;
        self.data = undefined;
        self.callbacks = [];

        function resolve(value) {
            if (self.status !== PENDDING) return;
            self.status = FULFILLED;
            self.data = value;
            // 當即執行異步回調函數
            setTimeout(() => {
                self.callbacks.forEach(callbacksObj => {
                    callbacksObj.onResolved(value);
                })
            })
        }

        function reject(reason) {
            if (self.status !== PENDDING) return;
            self.status = REJECTED;
            self.data = reason;
            setTimeout(() => {
                self.callbacks.forEach(callbacksObj => {
                    callbacksObj.onRejected(reason);
                })
            })
        }
        executor(resolve, reject)
    }
    window.MyPromise = MyPromise;
    1. Promise原型鏈上的then方法,能夠接收兩個參數(且是回調函數),成功/失敗,而且每次返回的都是一個新的Promise
// MyPromise原型鏈上存在then方法
MyPromise.prototype.then = function (onResolved, onRejected) {
    const self = this;
    return new MyPromise((resolve, reject) => { // 每次都返回一個新的Promise對象
        // 首先判斷當前狀態
        if (self.status === FULFILLED) {
            /* 
                一、返回的Promise的結果是由onResolved/onrejected決定的
                二、返回的是Promise對象 (根據執結果決定Promise的返回結果)
                三、返回的不是Promise對象 (該值就是Promise的返回結果)
                四、拋出異常 異常的值爲返回的結果
            */
            setTimeout(() => {
                try {
                    const result = onResolved(self.data);
                    if (reject instanceof MyPromise) {
                        result.then(value => {
                            resolve(value);
                        }, reason => {
                            reject(reason);
                        })
                    } else {
                        resolve(result);
                    }
    
                } catch (error) {
                    reject(error);
                }
            });
    
        } else if (self.status === REJECTED) {
            setTimeout(() => {
                try {
                    const result = onRejected(self.data);
                    if (reject instanceof MyPromise) {
                        result.then(value => {
                            resolve(value);
                        }, reason => {
                            reject(reason);
                        })
                    } else {
                        resolve(result);
                    }
    
                } catch (error) {
                    reject(error);
                }
            });
    
        } else if (self.status === PENDDING) {
            self.callbacks.push({
                onResolved() {
                    try {
                        const result = onResolved(self.data);
                        if (reject instanceof MyPromise) {
                            result.then(value => {
                                resolve(value);
                            }, reason => {
                                reject(reason);
                            })
                        } else {
                            resolve(result);
                        }
    
                    } catch (error) {
                        reject(error);
                    }
                },
                onRejected() {
                    try {
                        const result = onRejected(self.data);
                        if (reject instanceof MyPromise) {
                            result.then(value => {
                                resolve(value);
                            }, reason => {
                                reject(reason);
                            })
                        } else {
                            resolve(result);
                        }
    
                    } catch (error) {
                        reject(error);
                    }
                }
            })
        }
    })
}
  • 好的停一下,一步一步講解
    1. .then每次都返回一個新的Promise,因此在.then方法裏是

> return new MyPromise((resolve,reject)){}css

    1. 每一種狀態都存在返回值,而且都能是一下三種狀況
    2. 返回的是Promise對象
    3. 返回的不是Promise對象
    4. 拋出異常
    1. FULFILLED/REJECTED兩種狀態須要當即執行異步函數
    1. PENDDING爲何沒有當即執行異步函數,由於當狀態爲PENDDING時就執行then,會先往待執行回調函數的數組(callbacks)內存放這個回調,緊接着在回到Promise的執行其中執行resolve/reject,而上面也寫過了,執行resolve/reject會去待執行回調函數的數組內遍歷並賦值。

  • 好的繼續,而且對上面重複的優化一下。
// MyPromise原型鏈上存在then方法
    MyPromise.prototype.then = function (onResolved, onRejected) {
        const self = this;
        return new MyPromise((resolve, reject) => { // 每次都返回一個新的Promise對象
            function handle(callback) {
                /* 
                    一、返回的Promise的結果是由onResolved/onrejected決定的
                    二、返回的是Promise對象 (根據執結果決定Promise的返回結果)
                    三、返回的不是Promise對象 (該值就是Promise的返回結果)
                    四、拋出異常 異常的值爲返回的結果
                */
                try {
                    const result = callback(self.data);
                    if (reject instanceof MyPromise) {
                        result.then(value => {
                            resolve(value);
                        }, reason => {
                            reject(reason);
                        })
                    } else {
                        resolve(result);
                    }

                } catch (error) {
                    reject(error);
                }
            }
            // 首先判斷當前狀態
            if (self.status === FULFILLED) {
                setTimeout(() => {
                    thandle(onResolved)
                });

            } else if (self.status === REJECTED) {
                setTimeout(() => {
                    thandle(onRejected)
                });

            } else if (self.status === PENDDING) {
                self.callbacks.push({
                    onResolved() {
                        handle(onResolved)
                    },
                    onRejected() {
                        handle(onRejected)
                    }
                })
            }
        })
    }
    1. 防止不穿成功或者失敗的回調函數,給成功和失敗都給一個默認回調函數
MyPromise.prototype.then = function (onResolved, onRejected) {
        const self = this;
        // 定義默認回調
        onResolved = typeof onResolved === "function" ? onResolved : value => value;
        onRejected = typeof onRejected === "function" ? onRejected : reason => {throw reason};
        return new MyPromise((resolve, reject) => { // 每次都返回一個新的Promise對象
            function handle(callback) {
                /* 
                    一、返回的Promise的結果是由onResolved/onrejected決定的
                    二、返回的是Promise對象 (根據執結果決定Promise的返回結果)
                    三、返回的不是Promise對象 (該值就是Promise的返回結果)
                    四、拋出異常 異常的值爲返回的結果
                */
                try {
                    const result = callback(self.data);
                    if (reject instanceof MyPromise) {
                        result.then(value => {
                            resolve(value);
                        }, reason => {
                            reject(reason);
                        })
                    } else {
                        resolve(result);
                    }

                } catch (error) {
                    reject(error);
                }
            }
            // 首先判斷當前狀態
            if (self.status === FULFILLED) {
                setTimeout(() => {
                    thandle(onResolved)
                });

            } else if (self.status === REJECTED) {
                setTimeout(() => {
                    thandle(onRejected)
                });

            } else if (self.status === PENDDING) {
                self.callbacks.push({
                    onResolved() {
                        handle(onResolved)
                    },
                    onRejected() {
                        handle(onRejected)
                    }
                })
            }
        })
    }
    1. 接着咱們看看catch,其實就是
Promise.prototype.then(undefined,rejected)
  • 或者
Promise.prototype.then(null,rejected)
//MyPromise原型鏈上存在catch方法
  MyPromise.prototype.catch = function (onRejected) {
    return this.then(null, onRejected);
  }
  • 七、接下來實現一下 Promise.resolve/Promise.reject
/MyPromise實例對象上存在resolve方法
MyPromise.resolve = function (value) {
    if (value instanceof MyPromise) return value;
    return new MyPromise(resolve => resolve(value))             // 返回一個resolved狀態的Promise對象
}

//MyPromise實例對象上存在reject方法
MyPromise.reject = function (reason) {
    return new MyPromise((resolve,reject) => reject(reason));  // 返回一個reject狀態Promise對象
}
    1. 接下來實現一下Promise.all/Promise.race
//MyPromise實例對象上存在all方法
MyPromise.all = function (promises) {
    let promisesCount = 0
    let values = new Array(promises.length);
    return new MyPromise((resolve,reject)=>{
        promises.forEach((promise,index)=>{
            promise.then(value => {
                promisesCount++;
                values[index] = value;
                if (promisesCount === promises.length){
                    resolve(values);
                }
            },reason => {
                reject(reason);
            })
        })
    })

}
  • 好的,咱們來看看Promise.all實現的思路html

      1. Promise.all 傳入的是一個數組
      1. Promise.all返回的是一個數組
      1. Promise.all傳入的數組中,每一個Promise對象必須都正確才能返回正確的結果數組
      1. Promise.all傳入的數組中任意一個對象返回錯的結果,都會返回錯誤的結果
  • 好的,其實咱們還少一個步驟就是Promise.all傳入的數組的參數能夠不是Promise的實例, 因此數組參數若是不是Promise實例,先調用Promise.resolve
//MyPromise實例對象上存在all方法
MyPromise.all = function (promises) {
    let promisesCount = 0
    let values = new Array(promises.length);
    return new MyPromise((resolve, reject) => {
      promises.forEach((promise, index) => {
        MyPromise.resolve(promise).then(value => {
          promisesCount++;
          values[index] = value;
          if (promisesCount === promises.length) {
            resolve(values);
          }
        }, reason => {
          reject(reason);
        })
      })
    })
}
  • Promise.race實現
//MyPromise實例對象上存在race方法
  MyPromise.race = function (promises) {
    return new MyPromise((resolve, reject) => {
      promises.forEach(promise => {
        MyPromise.resolve(promise).then(value => {
          resolve(value);
        }, reason => {
          reject(reason)
        })
      })
    })
  }
    • 好的,解釋一下,前端

        1. Promise.race傳入的也是一個數組
        1. 傳入的Promise執行內容相同的狀況下,Promise.race返回的結果爲數組中的第一個值
        1. 若傳入的Promise執行內容不一致,有前後區分,則結果爲執行的最快的一個
    • 至此從零手寫一個Promise完成了,其中包括
    Promise.prototype.then

    Promise.prototype.catch數組

    Promise.resolvepromise

    Promise.reject異步

    Promise.all函數

    Promise.race學習

    (function (window) {
    
      const PENDDING = 'pendding';
      const FULFILLED = 'fulfilled';
      const REJECTED = 'rejected';
      // 定義MyPromise
      function MyPromise(executor) {
        const self = this;
        self.status = PENDDING;
        self.data = undefined;
        self.callbacks = [];
    
        function resolve(value) {
          if (self.status !== PENDDING) return;
          self.status = FULFILLED;
          self.data = value;
          // 當即執行異步回調函數
          setTimeout(() => {
            self.callbacks.forEach(callbacksObj => {
              callbacksObj.onResolved(value);
            })
          })
        }
    
        function reject(reason) {
          if (self.status !== PENDDING) return;
          self.status = REJECTED;
          self.data = reason;
          setTimeout(() => {
            self.callbacks.forEach(callbacksObj => {
              callbacksObj.onRejected(reason);
            })
          })
        }
        try{
          executor(resolve, reject)
        }catch(error){
          reject(error)
        }
        
      }
      // MyPromise原型鏈上存在then方法
      MyPromise.prototype.then = function (onResolved, onRejected) {
        const self = this;
        // 定義默認回調
        onResolved = typeof onResolved === "function" ? onResolved : value => value;
        onRejected = typeof onRejected === "function" ? onRejected : reason => {
          throw reason
        };
        return new MyPromise((resolve, reject) => { // 每次都返回一個新的Promise對象
          function handle(callback) {
            /* 
                一、返回的Promise的結果是由onResolved/onrejected決定的
                二、返回的是Promise對象 (根據執結果決定Promise的返回結果)
                三、返回的不是Promise對象 (該值就是Promise的返回結果)
                四、拋出異常 異常的值爲返回的結果
            */
            try {
              const result = callback(self.data);
              if (reject instanceof MyPromise) {
                result.then(value => {
                  resolve(value);
                }, reason => {
                  reject(reason);
                })
              } else {
                resolve(result);
              }
    
            } catch (error) {
              reject(error);
            }
          }
          // 首先判斷當前狀態
          if (self.status === FULFILLED) {
            setTimeout(() => {
              handle(onResolved)
            });
    
          } else if (self.status === REJECTED) {
            setTimeout(() => {
              handle(onRejected)
            });
    
          } else if (self.status === PENDDING) {
            self.callbacks.push({
              onResolved() {
                handle(onResolved)
              },
              onRejected() {
                handle(onRejected)
              }
            })
          }
        })
      }
      //MyPromise原型鏈上存在catch方法
      MyPromise.prototype.catch = function (onRejected) {
        return this.then(null, onRejected);
      }
    
      //MyPromise實例對象上存在resolve方法
      MyPromise.resolve = function (value) {
        if (value instanceof MyPromise) return value;
        return new MyPromise(resolve => resolve(value)) // 返回一個resolved狀態的Promise對象
      }
    
      //MyPromise實例對象上存在reject方法
      MyPromise.reject = function (reason) {
        return new MyPromise((resolve, reject) => reject(reason)); // 返回一個reject狀態Promise對象
      }
    
      //MyPromise實例對象上存在all方法
      MyPromise.all = function (promises) {
        let promisesCount = 0
        let values = new Array(promises.length);
        return new MyPromise((resolve, reject) => {
          promises.forEach((promise, index) => {
            MyPromise.resolve(promise).then(value => {
              promisesCount++;
              values[index] = value;
              if (promisesCount === promises.length) {
                resolve(values);
              }
            }, reason => {
              reject(reason);
            })
          })
        })
      }
    
      //MyPromise實例對象上存在race方法
      MyPromise.race = function (promises) {
        return new MyPromise((resolve, reject) => {
          promises.forEach(promise => {
            MyPromise.resolve(promise).then(value => {
              resolve(value);
            }, reason => {
              reject(reason)
            })
          })
        })
      }
    
      window.MyPromise = MyPromise;
    })(window)
    • 最後咱們用類(class)的方式實現一下
    (function (window) {
        const PENDDING = 'pendding';
        const FULFILLED = 'fulfilled';
        const REJECTED = 'rejected';
        // 定義MyPromise
        class MyPromise {
            constructor(executor) {
                const self = this;
                self.status = PENDDING;
                self.data = undefined;
                self.callbacks = [];
    
                function resolve(value) {
                    if (self.status !== PENDDING) return;
                    self.status = FULFILLED;
                    self.data = value;
                    // 當即執行異步回調函數
                    setTimeout(() => {
                        self.callbacks.forEach(callbacksObj => {
                            callbacksObj.onResolved(value);
                        })
                    })
                }
    
                function reject(reason) {
                    if (self.status !== PENDDING) return;
                    self.status = REJECTED;
                    self.data = reason;
                    setTimeout(() => {
                        self.callbacks.forEach(callbacksObj => {
                            callbacksObj.onRejected(reason);
                        })
                    })
                }
                executor(resolve, reject)
            }
            // MyPromise原型鏈上存在then方法
            then(onResolved, onRejected) {
                const self = this;
                // 定義默認回調
                onResolved = typeof onResolved === "function" ? onResolved : value => value;
                onRejected = typeof onRejected === "function" ? onRejected : reason => {
                    throw reason
                };
                return new MyPromise((resolve, reject) => { // 每次都返回一個新的Promise對象
                    function handle(callback) {
                        /* 
                            一、返回的Promise的結果是由onResolved/onrejected決定的
                            二、返回的是Promise對象 (根據執結果決定Promise的返回結果)
                            三、返回的不是Promise對象 (該值就是Promise的返回結果)
                            四、拋出異常 異常的值爲返回的結果
                        */
                        try {
                            const result = callback(self.data);
                            if (reject instanceof MyPromise) {
                                result.then(value => {
                                    resolve(value);
                                }, reason => {
                                    reject(reason);
                                })
                            } else {
                                resolve(result);
                            }
    
                        } catch (error) {
                            reject(error);
                        }
                    }
                    // 首先判斷當前狀態
                    if (self.status === FULFILLED) {
                        setTimeout(() => {
                            handle(onResolved)
                        });
    
                    } else if (self.status === REJECTED) {
                        setTimeout(() => {
                            handle(onRejected)
                        });
    
                    } else if (self.status === PENDDING) {
                        self.callbacks.push({
                            onResolved() {
                                handle(onResolved)
                            },
                            onRejected() {
                                handle(onRejected)
                            }
                        })
                    }
                })
            }
            //MyPromise原型鏈上存在catch方法
            catch (onRejected) {
                return this.then(null, onRejected);
            }
            //MyPromise實例對象上存在resolve方法
            static resolve(value) {
                if (value instanceof MyPromise) return value;
                return new MyPromise(resolve => resolve(value)) // 返回一個resolved狀態的Promise對象
            }
            //MyPromise實例對象上存在reject方法
            static reject(reason) {
                return new MyPromise((resolve, reject) => reject(reason)); // 返回一個reject狀態Promise對象
            }
            //MyPromise實例對象上存在all方法
            static all(promises) {
                let promisesCount = 0
                let values = new Array(promises.length);
                return new MyPromise((resolve, reject) => {
                    promises.forEach((promise, index) => {
                        MyPromise.resolve(promise).then(value => {
                            promisesCount++;
                            values[index] = value;
                            if (promisesCount === promises.length) {
                                resolve(values);
                            }
                        }, reason => {
                            reject(reason);
                        })
                    })
                })
            }
            //MyPromise實例對象上存在race方法
            static race(promises) {
                return new MyPromise((resolve, reject) => {
                    promises.forEach(promise => {
                        MyPromise.resolve(promise).then(value => {
                            resolve(value);
                        }, reason => {
                            reject(reason)
                        })
                    })
                })
            }
        }
        window.MyPromise = MyPromise;
    })(window)
    • 從零手寫Promise說難也不難,可是仍是花了很多時間的,但願可以幫助到像我同樣想學好js,想學好Promise的朋友,一塊兒加油吧。

    最後

    • 若是你想加入特皮技術團隊,有人指導你學習,提高本身,能夠公衆號聯繫我
    • 感受對你有幫助,能夠點個在看,轉發一下,關注咱們公衆號:【前端巔峯
    相關文章
    相關標籤/搜索