主頁 >  其他 > 前端Promise總結筆記

前端Promise總結筆記

2021-04-17 10:45:17 其他

目錄

    • 一.什么是Promise:
    • 二.為啥使用Promise:
    • 三. promise初體驗:
    • 四:promise體驗ajax請求:
    • 五:Promise封裝ajax請求:
    • 六:promise的狀態改變:
    • 七:Promise基本流程圖:
    • 八:Promise的API 使用:
            • 1. Promise 的建構式:Promise(executor){}
            • 2. Promise.prototype.then 方法: (onResolved, onRejected)=> {}
            • 3.Promise.prototype.catch萬法: (onRejected) => {}
            • 4. Promise.resolve 方法: (value)=> {}
            • 5. Promise.reject 方法: (reason) => {}
            • 6. Promise.all 方法: (promises)=> {}
            • 7. Promise.race 方法: (promises)=> {}
    • 九:使用Promise面臨的關鍵問題:
            • 1.如何改變 promise的狀態?
            • 2.一個 promise指定多個成功/失敗回呼函式,都會呼叫嗎?
            • 4. promise.then()回傳的新promise的結果狀態由什么決定?
            • 5. promise 如何串連多個操作任務?
            • 6. promise 的例外穿透,
            • 7.中斷 promise鏈,
    • 十:Promise的自定義封裝:
            • 1.初始化結構搭建:
            • 2. 搭建resolve與reject結構:
            • 3. 實作resolve與reject函式:
            • 4. throw拋出例外改變狀態:
            • 5. 設定Promise物件狀態只能修改一次:
            • 6. then()方法執行回呼:
            • 7.執行異步任務回呼:
            • 8.能執行多個回呼:
            • 9.同步任務 then()的回傳結果:
            • 10.異步任務 then()的回傳結果:
            • 11. 完善then()方法與優化:
            • 12. 實作catch方法與例外穿透:
            • 13. 封裝Promise.resolve()方法:
            • 14. 封裝Promise.reject方法:
            • 15. 封裝Promise.all方法:
            • 16. 封裝Promise.race方法:
            • 17.回呼函式異步執行:
            • 18.class版本封裝:
    • 十一:async函式:
            • 1.回傳一個非Promise物件,回傳值是resolve,
            • 2.如果回傳是一個Promise物件,由回傳結果決定:
            • 3.拋出例外也是失敗:
    • 十二.await運算式:
            • 1.右側為promise物件:
            • 2.右側為其它值:
            • 3.如果promise是失敗狀態:
    • 十三.async與await結合發生ajax請求:
    • 十四.總結:

一.什么是Promise:

  1. Promise 是在 js 中進行異步編程的新解決方案,(以前舊的方案是單純使用回呼函式)
  2. 從語法來說,promise是一個建構式,
  3. 從功能來說,promise物件用來封裝一個異步操作,并且可以獲得成功或失敗的回傳值,
  4. JS中的常見的異步操作:定時器,AJAX中一般也是異步操作(也可以同步),回呼函式可以理解為異步(不是嚴謹的異步操作)…等,
    剩下的都是同步處理

二.為啥使用Promise:

  1. promise使用回呼函式更靈活,舊的回呼函式必須在啟動異步任務前指定,
  2. promise:啟動異步任務 => 回傳promise物件 => 給promise物件系結回呼函式(甚至能在異步任務結束后指定多個)
  3. promise支持鏈式呼叫,可以解決回呼地獄問題,(回呼地獄就是多層回呼函式嵌套使用,就是套娃,這樣就不利于閱讀和例外處理,)

三. promise初體驗:

效果:點擊一個按鈕,有30%概率顯示中獎,
實作: 點擊按鈕后得到一個1到100間的亂數,小于等于30輸出中獎,否則輸出沒中,期間用定時器模擬異步操作,在定時器里執行判斷,
(1)基礎的寫法:

<button id="btn">click</button>
    <script>
        var btn = document.querySelector("#btn");
    // 該函式回傳一個兩數之間的隨機整數,包括兩個數在內
    function getRandomIntInclusive(min, max) {
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值 
    }
    // 點擊事件
     btn.addEventListener('click',function(){
         // 1秒的定時器,模擬異步操作
         setTimeout(() => {
             // 得到1到100間的一個數
             let n = getRandomIntInclusive(1, 100);
             if (n <= 30) {
                 alert('中獎嘍');
             } else {
                 alert('沒中獎');
             }
         }, 1000);
     })
    </script>

在這里插入圖片描述
(2)promise寫法,在promise里封裝一個異步操作,

    <script>
        var btn = document.querySelector("#btn");
    // 得到一個兩數之間的隨機整數,包括兩個數在內
    function getRandomIntInclusive(min, max) {
        min = Math.ceil(min);
        max = Math.floor(max);
        return Math.floor(Math.random() * (max - min + 1)) + min; //含最大值,含最小值 
    }
    // 點擊事件
     btn.addEventListener('click',function(){
         // 下面是promise ,resolve表示解決,reject表示拒絕 ,都是函式型別資料,
         const p = new Promise((resolve,reject) => {
             setTimeout(()=>{
                  let n = getRandomIntInclusive(1, 100);
                  if(n<=30){
                      resolve(); //將promise狀態設為 “成功”
                  }else{
                      reject(); //將promise狀態設為 “失敗”
                  }
             },1000)
         });
         // 呼叫then方法
         p.then(()=>{
             // “成功”執行這步
            alert('中獎嘍');
         },()=>{
             // “失敗”執行這步
            alert('沒中獎');
         })
     })

假如要在上面輸出結果后加上選中的號碼:
因為.then()里并不能直接獲得 n,所以在resolve與reject里把n當結果值回傳,

 // 點擊事件
     btn.addEventListener('click',function(){
         // 下面是promise ,resolve表示解決,reject表示拒絕 ,都是函式型別資料,
         const p = new Promise((resolve,reject) => {
             setTimeout(()=>{
                  let n = getRandomIntInclusive(1, 100);
                  if(n<=30){
                      resolve(n); //將promise狀態設為 “成功”,并把結果值n回傳
                  }else{
                      reject(n); //將promise狀態設為 “失敗”,并把結果值n回傳
                  }
             },1000)
         });
         // 呼叫then方法
         // value為值的意思,reason為理由的意思,都是形參
         p.then((value)=>{
             // “成功”執行
            alert('中獎嘍'+value);
         },(reason)=>{
             // “失敗”執行
            alert('沒中獎'+reason);
         })
     })

在這里插入圖片描述

四:promise體驗ajax請求:

這是一個開源社區的api檔案,有許多api,
效果:點擊按鈕獲得一句名言在控制臺輸出,
基礎寫法:

 <script>
        var btn = document.querySelector("#btn");
    // 點擊事件
      btn.addEventListener('click',function(){
         //創建物件
         const xhr = new XMLHttpRequest();
         //初始化
         xhr.open('GET',"http://poetry.apiopen.top/sentences");
         //發送
         xhr.send();
         //處理回應結果
         xhr.onreadystatechange = function(){
             if(xhr.readyState === 4){
                 if(xhr.status >=200 && xhr.status < 300){
                     //輸出回應體
                     console.log(xhr.response);
                 }else{
                     //輸出回應狀態碼
                     console.log(xhr.status);
                 }
             }
         }
     })
    </script>

在這里插入圖片描述
promise封裝:

 // 點擊事件
     btn.addEventListener('click',function(){
         const p = new Promise((resolve,reject) => {
              //創建物件
         const xhr = new XMLHttpRequest();
             //初始化
             xhr.open('GET', "http://poetry.apiopen.top/sentences");
             //發送
             xhr.send();
             //處理回應結果
             xhr.onreadystatechange = function () {
                 if (xhr.readyState === 4) {
                     if (xhr.status >= 200 && xhr.status < 300) {
                         //輸出回應體
                        resolve(xhr.response);
                     } else {
                         //輸出回應狀態碼
                         reject(xhr.status);
                     }
                 }
             }
         })
         p.then(value=>{
              console.log(value);
         },reason=>{
             //控制臺輸出警告資訊
               console.warn(reason);
         })
     })

在這里插入圖片描述
若把介面寫錯:
在這里插入圖片描述

五:Promise封裝ajax請求:

跟上一步差不多,就是把其封裝在一個sendAJAX()的自定義函式里,


function sendAJAX(url) {
         return new Promise((resolve, reject) => {
                //創建物件
                const xhr = new XMLHttpRequest();
                xhr.responseType = 'json';
                //初始化
                xhr.open('GET', url);
                //發送
                xhr.send();
                //處理回應結果
                xhr.onreadystatechange = function () {
                    if (xhr.readyState === 4) {
                        if (xhr.status >= 200 && xhr.status < 300) {
                            //輸出回應體
                            resolve(xhr.response);
                        } else {
                            //輸出回應狀態碼
                            reject(xhr.status);
                        }
                    }
                }
            });
     }
      
     sendAJAX("http://poetry.apiopen.top/sentences")
     .then(value=>{
              console.log(value);
         },reason=>{
             //控制臺輸出警告資訊
               console.warn(reason);
         })

六:promise的狀態改變:

promise狀態表示實體物件的一個屬性【PromiseState】,包括以下值:
(1)pending 未決定的
(2)resolved 或 fullfilled 成功
(3)rejected 失敗
Promise物件的值表示實體物件的另一個屬性【PromiseResult】,保存著物件【成功/失敗】的結果,而其狀態改變只有以下兩種可能:
(1)pending 變為resolved
(2)pending 變為 rejected
注:一個promise物件只能改變一次,無論成功或失敗都會有一個結果資料,成功的稱為 value , 失敗的稱為 reason ,

七:Promise基本流程圖:

在這里插入圖片描述

八:Promise的API 使用:

1. Promise 的建構式:Promise(executor){}

(1)executor 函式:執行器 (resolve,reject)=> {}
(2)resolve 函式:內部定義成功時呼叫函式 value => {} ,
(3)reject 函式:內部定義失敗時呼叫函式 reason => {} ,
注意:Promise內部會立同步即呼叫executor,異步操作在執行器里執行,

2. Promise.prototype.then 方法: (onResolved, onRejected)=> {}

(1) onResolved 函式:成功的回呼函式 (value) => {}
(2) onRejected 函式:失敗的回呼函式 (reason) => {}
注:指定用于得到成功value的成功回呼和用于得到失敗reason的失敗回呼是回傳一個新的promise物件,

3.Promise.prototype.catch萬法: (onRejected) => {}

onRejected.函式: 失敗的回呼函式**(reason)=> {}**
注:只是失敗的呼叫,then()的語法糖,相當于: then(undefined, onRejected),

4. Promise.resolve 方法: (value)=> {}

value: 成功的資料或promise物件
注:如果傳入的引數為非Promise類 型的物件,則回傳的結果為成功promise物件,如果傳入的引數為Promise 物件,則引數的結果決定了resolve 的結果,

5. Promise.reject 方法: (reason) => {}

reason: 失敗的原因
注:無論傳入啥只回傳一個失敗的promise物件,

6. Promise.all 方法: (promises)=> {}

promises: 包含n個promise的陣列
注:回傳一個新的promise,只有所有的promise都成功才成功,只要有一個失敗了就直接失敗,失敗了回傳那個失敗值,

7. Promise.race 方法: (promises)=> {}

promises: 包含n個promise的陣列
注:回傳一個新的promise,第一個完成的promise的結果狀態就是最終的結果狀態,
來一個例子:

 let p1 = new Promise((resolve,reject)=>{
          setTimeout(()=>{
              resolve('yes');
          },1000)
      })
      let p2 = Promise.resolve('success');
      let p3 = Promise.resolve('come');

      const result = Promise.race([p1,p2,p3]);
      console.log(result);

在這里插入圖片描述

九:使用Promise面臨的關鍵問題:

1.如何改變 promise的狀態?

(1) resolve(value): 如果當前是pending就會變為resolved,
(2) reject(reason): 如果當前是pending就會變為rejected,
(3)拋出例外 throw :如果當前是pending就會變為rejected,

 let p1 = new Promise((resolve,reject)=>{
           //  resolve('success');
         //    reject('error');
          //   throw 'error';
      })
2.一個 promise指定多個成功/失敗回呼函式,都會呼叫嗎?

當promise改變為對應狀態時都會呼叫,

 let p = new Promise((resolve,reject)=>{
            resolve('success');
      })
      // 第一次回呼
      p.then(value=>{
          console.log("yes");
      })
      // 第二次回呼
      p.then(value=>{
          console.log("oh yes");
      })

在這里插入圖片描述
3.改變 promiseT狀態和指定回呼函式誰先誰后?

(1)都有可能, 正常情況下是先指定回呼再改變狀態,但也可以先改狀態再指定回呼
(2)如何先改狀態再指定回呼?
①在執行 器中直接呼叫resolve(/reject();
②延遲更 長時間才呼叫then();
(3)什么時候才能得到資料?
①如果先指定的回呼, 那當狀態發生改變時,回呼函式就會呼叫,得到資料
②如果先改變的狀態, 那當指定回呼時,回呼函式就會呼叫,得到資料

4. promise.then()回傳的新promise的結果狀態由什么決定?

(1)簡單表達: then()指定的回呼函式執行的結果決定,
(2)詳細表達:
*如果拋出例外, 新promise變為rejected, reaon為拋出的例外,
*如果回傳的是非prormise的任意值,新promise變為resolved, value為回傳的值,
*如果回傳的是另一個新promise,此promise的結果就會成為新promise的結果,

隨筆:

let p = new Promise((resolve,reject) => {
            // resolve('success'); 
           // reject('No'); 
          //  throw 'oh no';
      });    
      let result = p.then(value => {
           console.log(value);
      }, reason => {
           console.warn(reason);   
      });     
      console.log(result);
5. promise 如何串連多個操作任務?

(1) promise 的then()回傳一個新的promise,可以開成then()的鏈式呼叫,
(2)通過then的鏈式呼叫串連多個同步/異步任務,

 let p =new Promise((resolve,reject) => {
          resolve("yes");
     })
     p.then(value => {
          return new Promise((resolve,reject)=>{
              resolve("oh yes~");
          });
     }).then(value => {
          console.log(value);
     })

輸出結果:
oh yes~

 let p =new Promise((resolve,reject) => {
          resolve("yes");
     })
     p.then(value => {
          return new Promise((resolve,reject)=>{
              resolve("oh yes~");
          });
     }).then(value => {
          console.log(value);
     }).then(value => {
          console.log(value);
     })

輸出結果:
oh yes~
undefined

6. promise 的例外穿透,

(1)當使用promise的then鏈式呼叫時,可以在最后指定失敗的回呼,
(2)前面任何操作出 了例外,都會傳到最后失敗的回呼中處理,

 let p =new Promise((resolve,reject) => {
         setTimeout(()=>{
            resolve("yes");
         },1000);
     })
     p.then(value => {
          throw 'oh No';
     }).then(value => {
          console.log("123");
     }).then(value => {
          console.log("456");
     }).catch(reason=>{
         console.warn(reason);
     })

輸出結果:
oh No

7.中斷 promise鏈,

(1)當使用promise的then鏈式呼叫時,在中間中斷,不再呼叫后面的回呼函式,
(2)辦法:在回呼函式中回傳一個pendding狀態的promise物件,

未中斷:

 let p =new Promise((resolve,reject) => {
         setTimeout(()=>{
            resolve("yes");
         },1000);
     })
     p.then(value => {
          console.log("789");
     }).then(value => {
          console.log("123");
     }).then(value => {
          console.log("456");
     }).catch(reason=>{
         console.warn(reason);
     })

輸出結果:
789
123
456

中斷:

 let p =new Promise((resolve,reject) => {
         setTimeout(()=>{
            resolve("yes");
         },1000);
     })
     p.then(value => {
          console.log("789");
          return new Promise(()=>{});
     }).then(value => {
          console.log("123");
     }).then(value => {
          console.log("456");
     }).catch(reason=>{
         console.warn(reason);
     })

輸出結果:
789

十:Promise的自定義封裝:

1.初始化結構搭建:
 // 自定義函式 Promise
     function Promise(executor){

     }
     // 添加then方法
     Promise.prototype.then = function(onResolved,onRejected){
         
     }

注:prototype 屬性使您有能力向物件添加屬性和方法,

2. 搭建resolve與reject結構:
 // 自定義函式Promise
     function Promise(executor){
          //自定義resolve函式,名字不一定用resolve
          function resolve(data){

          }
          //自定義reject函式
          function reject(data){

          }
          //同步呼叫【執行器函式】
          executor(resolve,reject);          
     }
     // 添加then方法
     Promise.prototype.then = function(onResolved,onRejected){
         
     }
3. 實作resolve與reject函式:
 // 自定義函式Promise
     function Promise(executor){
          //添加狀態屬性與結果值屬性
          this.PromiseState = 'pending';
          this.PromiseResult = null;
           //保存實體物件的this值
           const that = this;
          //自定義resolve函式,名字不一定用resolve
          function resolve(data){
             //改變狀態屬性
             that.PromiseState = 'fulfilled';  // 或者 resolved 
             //改變結果值屬性
             that.PromiseResult =data;
          }
          //自定義reject函式
          function reject(data){
              //改變狀態屬性
             that.PromiseState = 'rejected';  
            //改變結果值屬性
             that.PromiseResult =data;
          }
          //同步呼叫【執行器函式】
          executor(resolve,reject);          
     }
     // 添加then方法
     Promise.prototype.then = function(onResolved,onRejected){
         
     }
4. throw拋出例外改變狀態:

采用 try{ }catch(){ } 與throw一起使用,

// 自定義函式Promise
 function Promise(executor){
      //添加狀態屬性與結果值屬性
      this.PromiseState = 'pending';
      this.PromiseResult = null;
       //保存實體物件的this值
       const that = this;
      //自定義resolve函式,名字不一定用resolve
      function resolve(data){
         //改變狀態屬性
         that.PromiseState = 'fulfilled';  // 或者 resolve 
         //改變結果值屬性
         that.PromiseResult =data;
      }
      //自定義reject函式
      function reject(data){
          //改變狀態屬性
         that.PromiseState = 'rejected';  
        //改變結果值屬性
         that.PromiseResult =data;
      }

      try{
      //同步呼叫【執行器函式】
      executor(resolve,reject);
      }catch(e){
          //更改Promise物件為失敗
          reject(e);
      }
      
 }
 // 添加then方法
 Promise.prototype.then = function(onResolved,onRejected){
     
 }

注:throw陳述句拋出一個錯誤,

5. 設定Promise物件狀態只能修改一次:

加個判斷就好,

// 自定義函式Promise
     function Promise(executor){
          //添加狀態屬性與結果值屬性
          this.PromiseState = 'pending';
          this.PromiseResult = null;
           //保存實體物件的this值
           const that = this;
          //自定義resolve函式,名字不一定用resolve
          function resolve(data){
            //判斷狀態是否修改過,改過就直接回傳
            if(that.PromiseState !== 'pending') return;
             //改變狀態屬性
             that.PromiseState = 'fulfilled';  // 或者 resolve 
             //改變結果值屬性
             that.PromiseResult =data;
          }
          //自定義reject函式
          function reject(data){
             //判斷狀態是否修改過,改過就直接回傳
            if(that.PromiseState !== 'pending') return;
              //改變狀態屬性
             that.PromiseState = 'rejected';  
            //改變結果值屬性
             that.PromiseResult =data;
          }

          try{
          //同步呼叫【執行器函式】
          executor(resolve,reject);
          }catch(e){
              //更改Promise物件為失敗
              reject(e);
          }
          
     }
     // 添加then方法
     Promise.prototype.then = function(onResolved,onRejected){
         
     }
6. then()方法執行回呼:
  // 自定義函式Promise
     function Promise(executor){
          //添加狀態屬性與結果值屬性
          this.PromiseState = 'pending';
          this.PromiseResult = null;
           //保存實體物件的this值
           const that = this;
          //自定義resolve函式,名字不一定用resolve
          function resolve(data){
            //判斷狀態是否修改過
            if(that.PromiseState !== 'pending') return;
             //改變狀態屬性
             that.PromiseState = 'fulfilled';  // 或者 resolve 
             //改變結果值屬性
             that.PromiseResult =data;
          }
          //自定義reject函式
          function reject(data){
             //判斷狀態是否修改過,改過就直接回傳
            if(that.PromiseState !== 'pending') return;
              //改變狀態屬性
             that.PromiseState = 'rejected';  
            //改變結果值屬性
             that.PromiseResult =data;
          }

          try{
          //同步呼叫【執行器函式】
          executor(resolve,reject);
          }catch(e){
              //更改Promise物件為失敗
              reject(e);
          }
          
     }
     // 添加then方法
     Promise.prototype.then = function(onResolved,onRejected){
         //如果Promise狀態為fulfilled回呼這個函式
         if(this.PromiseState === 'fulfilled'){
             //將結果值傳入
            onResolved(this.PromiseResult);
         }
         //如果Promise狀態為rejected回呼這個函式
         if(this.PromiseState === 'rejected'){
             //將結果值傳入
            onRejected(this.PromiseResult);
         }
     }
 
7.執行異步任務回呼:

異步任務一般先回呼才改變狀態,所以第6步的代碼執行順序就無法執行異步回呼,解決如下:

// 自定義函式Promise
 function Promise(executor){
      //添加狀態屬性與結果值屬性
      this.PromiseState = 'pending';
      this.PromiseResult = null;
      // 定義callback屬性,保存pending狀態的回呼函式
      this.callback = {};
       //保存實體物件的this值
       const that = this;
      //自定義resolve函式,名字不一定用resolve
      function resolve(data){
        //判斷狀態是否修改過
        if(that.PromiseState !== 'pending') return;
         //改變狀態屬性
         that.PromiseState = 'fulfilled';  // 或者 resolve 
         //改變結果值屬性
         that.PromiseResult =data;
          //異步任務成功后執行回呼函式
          if(that.callback.onResolved){
             that.callback.onResolved(data);
         }
      }
      //自定義reject函式
      function reject(data){
         //判斷狀態是否修改過,改過就直接回傳
        if(that.PromiseState !== 'pending') return;
          //改變狀態屬性
         that.PromiseState = 'rejected';  
        //改變結果值屬性
         that.PromiseResult =data;
         //異步任務失敗后執行回呼函式
         if(that.callback.onRejected){
             that.callback.onRejected(data);
         }
      }

      try{
      //同步呼叫【執行器函式】
      executor(resolve,reject);
      }catch(e){
          //更改Promise物件為失敗
          reject(e);
      }
      
 }
 // 添加then方法
 Promise.prototype.then = function(onResolved,onRejected){
     //如果Promise狀態為fulfilled回呼這個函式
     if(this.PromiseState === 'fulfilled'){
         //將結果值傳入
        onResolved(this.PromiseResult);
     }
     //如果Promise狀態為rejected回呼這個函式
     if(this.PromiseState === 'rejected'){
         //將結果值傳入
        onRejected(this.PromiseResult);
     }
      //如果Promise狀態為pending,保存回呼函式
      if(this.PromiseState === 'pending'){
        this.callback = {
            onResolved: onResolved,
            onRejected: onRejected
        }
     }
 }
8.能執行多個回呼:

用第7步寫法指定多個回呼時,最后一個then回呼會覆寫掉前面的,解決如下,把保存回呼函式的callbacks變為一個陣列:

// 自定義函式Promise
     function Promise(executor){
          //添加狀態屬性與結果值屬性
          this.PromiseState = 'pending';
          this.PromiseResult = null;
          // 定義callback屬性,保存pending狀態的回呼函式
          this.callbacks = [];
           //保存實體物件的this值
           const that = this;
          //自定義resolve函式,名字不一定用resolve
          function resolve(data){
            //判斷狀態是否修改過
            if(that.PromiseState !== 'pending') return;
             //改變狀態屬性
             that.PromiseState = 'fulfilled';  // 或者 resolve 
             //改變結果值屬性
             that.PromiseResult =data;
              //異步任務成功后執行回呼函式
              that.callbacks.forEach(item=>{
                  item.onResolved(data);
              })
          }
          //自定義reject函式
          function reject(data){
             //判斷狀態是否修改過,改過就直接回傳
            if(that.PromiseState !== 'pending') return;
              //改變狀態屬性
             that.PromiseState = 'rejected';  
            //改變結果值屬性
             that.PromiseResult =data;
             //異步任務失敗后執行回呼函式
            that.callbacks.forEach(item=>{
                item.onRejected(data);
            })
          }

          try{
          //同步呼叫【執行器函式】
          executor(resolve,reject);
          }catch(e){
              //更改Promise物件為失敗
              reject(e);
          }
          
     }
     // 添加then方法
     Promise.prototype.then = function(onResolved,onRejected){
         //如果Promise狀態為fulfilled回呼這個函式
         if(this.PromiseState === 'fulfilled'){
             //將結果值傳入
            onResolved(this.PromiseResult);
         }
         //如果Promise狀態為rejected回呼這個函式
         if(this.PromiseState === 'rejected'){
             //將結果值傳入
            onRejected(this.PromiseResult);
         }
          //如果Promise狀態為pending,保存回呼函式
          if(this.PromiseState === 'pending'){
            this.callbacks.push({
                onResolved: onResolved,
                onRejected: onRejected
            })
         }
     }

forEach()方法

9.同步任務 then()的回傳結果:

就是在then()里有實作有結果回傳:

const result = p.then(value => {
          console.log(value);
     },reason => {
         console.warn(reason);
     }) 
console.log(result);

解決:

// 自定義函式Promise
function Promise(executor){
          //添加狀態屬性與結果值屬性
          this.PromiseState = 'pending';
          this.PromiseResult = null;
          // 定義callback屬性,保存pending狀態的回呼函式
          this.callbacks = [];
           //保存實體物件的this值
           const that = this;
          //自定義resolve函式,名字不一定用resolve
          function resolve(data){
            //判斷狀態是否修改過
            if(that.PromiseState !== 'pending') return;
             //改變狀態屬性
             that.PromiseState = 'fulfilled';  // 或者 resolve 
             //改變結果值屬性
             that.PromiseResult =data;
              //異步任務成功后執行回呼函式
              that.callbacks.forEach(item=>{
                  item.onResolved(data);
              })
          }
          //自定義reject函式
          function reject(data){
             //判斷狀態是否修改過,改過就直接回傳
            if(that.PromiseState !== 'pending') return;
              //改變狀態屬性
             that.PromiseState = 'rejected';  
            //改變結果值屬性
             that.PromiseResult =data;
             //異步任務失敗后執行回呼函式
            that.callbacks.forEach(item=>{
                item.onRejected(data);
            })
          }

          try{
          //同步呼叫【執行器函式】
          executor(resolve,reject);
          }catch(e){
              //更改Promise物件為失敗
              reject(e);
          }
          
     }
     // 添加then方法
     Promise.prototype.then = function (onResolved, onRejected) {
            return new Promise((resolve, reject) => {
                //如果Promise狀態為fulfilled回呼這個函式
                if (this.PromiseState === 'fulfilled') {
                    try {
                        //獲取回呼函式執行結果
                        let result = onResolved(this.PromiseResult);
                        //判斷
                        if (result instanceof Promise) {
                            //如果是Promise物件
                            result.then(v => {
                                resolve(v);
                            }, r => {
                                reject(r);
                            })
                        } else {
                            //結果物件狀態為【成功】
                            resolve(result);
                        }
                    } catch (e) {
                        reject(e);
                    }
                }
                //如果Promise狀態為rejected回呼這個函式
                if (this.PromiseState === 'rejected') {
                    //將結果值傳入
                    onRejected(this.PromiseResult);
                }
                //如果Promise狀態為pending,保存回呼函式
                if (this.PromiseState === 'pending') {
                    this.callbacks.push({
                        onResolved: onResolved,
                        onRejected: onRejected
                    })
                }
            })
        }

注:instanceof 運算子用于檢測建構式的 prototype 屬性是否出現在某個實體物件的原型鏈上,

10.異步任務 then()的回傳結果:

(′?`」 ∠)
用第9步執行異步任務return回傳的會是pending狀態,
解決:

// 自定義函式Promise
function Promise(executor){
          //添加狀態屬性與結果值屬性
          this.PromiseState = 'pending';
          this.PromiseResult = null;
          // 定義callback屬性,保存pending狀態的回呼函式
          this.callbacks = [];
           //保存實體物件的this值
           const that = this;
          //自定義resolve函式,名字不一定用resolve
          function resolve(data){
            //判斷狀態是否修改過
            if(that.PromiseState !== 'pending') return;
             //改變狀態屬性
             that.PromiseState = 'fulfilled';  // 或者 resolve 
             //改變結果值屬性
             that.PromiseResult =data;
              //異步任務成功后執行回呼函式
              that.callbacks.forEach(item=>{
                  item.onResolved(data);
              })
          }
          //自定義reject函式
          function reject(data){
             //判斷狀態是否修改過,改過就直接回傳
            if(that.PromiseState !== 'pending') return;
              //改變狀態屬性
             that.PromiseState = 'rejected';  
            //改變結果值屬性
             that.PromiseResult =data;
             //異步任務失敗后執行回呼函式
            that.callbacks.forEach(item=>{
                item.onRejected(data);
            })
          }

          try{
          //同步呼叫【執行器函式】
          executor(resolve,reject);
          }catch(e){
              //更改Promise物件為失敗
              reject(e);
          }
          
     }
     // 添加then方法
     Promise.prototype.then = function (onResolved, onRejected) {
         const that = this;
            return new Promise((resolve, reject) => {
                //如果Promise狀態為fulfilled回呼這個函式
                if (this.PromiseState === 'fulfilled') {
                    try {
                        //將結果值傳入
                        let result = onResolved(this.PromiseResult);
                        //判斷
                        if (result instanceof Promise) {
                            //如果是Promise物件
                            result.then(v => {
                                resolve(v);
                            }, r => {
                                reject(r);
                            })
                        } else {
                            //結果物件狀態為【成功】
                            resolve(result);
                        }
                    } catch (e) {
                        reject(e);
                    }
                }
                //如果Promise狀態為rejected回呼這個函式
                if (this.PromiseState === 'rejected') {
                    //將結果值傳入
                    onRejected(this.PromiseResult);
                }
                //如果Promise狀態為pending,保存回呼函式
                if (this.PromiseState === 'pending') {
                    this.callbacks.push({
                        onResolved: function () {
                            try {
                                //執行成功回呼函式
                                let result = onResolved(that.PromiseResult);
                                //判斷
                                if (result instanceof Promise) {
                                    result.then(v => {
                                        resolve(v);
                                    }, r => {
                                        reject(r);
                                    })
                                } else {
                                    resolve(result);
                                }
                            } catch (e) {
                                reject(e);
                            }
                        },
                        onRejected: function () {
                            try {
                                //執行成功回呼函式
                                let result = onRejected(that.PromiseResult);
                                //判斷
                                if (result instanceof Promise) {
                                    result.then(v => {
                                        resolve(v);
                                    }, r => {
                                        reject(r);
                                    })
                                } else {
                                    resolve(result);
                                }
                            } catch(e){
                                reject(e);
                            }
                        }
                    })
                }
            })
        }
11. 完善then()方法與優化:
// 自定義函式Promise
function Promise(executor){
          //添加狀態屬性與結果值屬性
          this.PromiseState = 'pending';
          this.PromiseResult = null;
          // 定義callback屬性,保存pending狀態的回呼函式
          this.callbacks = [];
           //保存實體物件的this值
           const that = this;
          //自定義resolve函式,名字不一定用resolve
          function resolve(data){
            //判斷狀態是否修改過
            if(that.PromiseState !== 'pending') return;
             //改變狀態屬性
             that.PromiseState = 'fulfilled';  // 或者 resolve 
             //改變結果值屬性
             that.PromiseResult =data;
              //異步任務成功后執行回呼函式
              that.callbacks.forEach(item=>{
                  item.onResolved(data);
              })
          }
          //自定義reject函式
          function reject(data){
             //判斷狀態是否修改過,改過就直接回傳
            if(that.PromiseState !== 'pending') return;
              //改變狀態屬性
             that.PromiseState = 'rejected';  
            //改變結果值屬性
             that.PromiseResult =data;
             //異步任務失敗后執行回呼函式
            that.callbacks.forEach(item=>{
                item.onRejected(data);
            })
          }

          try{
          //同步呼叫【執行器函式】
          executor(resolve,reject);
          }catch(e){
              //更改Promise物件為失敗
              reject(e);
          }
          
     }
     // 添加then方法
     Promise.prototype.then = function (onResolved, onRejected) {
         const that = this;
            return new Promise((resolve, reject) => {
                //封裝重復的部分
                function callback(type){
                    try {
                        //將結果值傳入
                        let result = type(that.PromiseResult);
                        //判斷
                        if (result instanceof Promise) {
                            //如果是Promise物件
                            result.then(v => {
                                resolve(v);
                            }, r => {
                                reject(r);
                            })
                        } else {
                            //結果物件狀態為【成功】
                            resolve(result);
                        }
                    } catch (e) {
                        reject(e);
                    }
                }
                //如果Promise狀態為fulfilled回呼這個函式
                if (this.PromiseState === 'fulfilled') {
                    callback(onResolved);
                }
                //如果Promise狀態為rejected回呼這個函式
                if (this.PromiseState === 'rejected') {
                    callback(onRejected);
                }
                //如果Promise狀態為pending,保存回呼函式
                if (this.PromiseState === 'pending') {
                    this.callbacks.push({
                        onResolved: function () {
                            callback(onResolved);
                        },
                        onRejected: function () {
                            callback(onRejected);
                        }
                    })
                }
            })
        }
12. 實作catch方法與例外穿透:
// 自定義函式Promise
function Promise(executor){
          //添加狀態屬性與結果值屬性
          this.PromiseState = 'pending';
          this.PromiseResult = null;
          // 定義callback屬性,保存pending狀態的回呼函式
          this.callbacks = [];
           //保存實體物件的this值
           const that = this;
          //自定義resolve函式,名字不一定用resolve
          function resolve(data){
            //判斷狀態是否修改過
            if(that.PromiseState !== 'pending') return;
             //改變狀態屬性
             that.PromiseState = 'fulfilled';  // 或者 resolve 
             //改變結果值屬性
             that.PromiseResult =data;
              //異步任務成功后執行回呼函式
              that.callbacks.forEach(item=>{
                  item.onResolved(data);
              })
          }
          //自定義reject函式
          function reject(data){
             //判斷狀態是否修改過,改過就直接回傳
            if(that.PromiseState !== 'pending') return;
              //改變狀態屬性
             that.PromiseState = 'rejected';  
            //改變結果值屬性
             that.PromiseResult =data;
             //異步任務失敗后執行回呼函式
            that.callbacks.forEach(item=>{
                item.onRejected(data);
            })
          }

          try{
          //同步呼叫【執行器函式】
          executor(resolve,reject);
          }catch(e){
              //更改Promise物件為失敗
              reject(e);
          }
          
     }
     // 添加then方法
     Promise.prototype.then = function (onResolved, onRejected) {
         const that = this;
         //判斷回呼引數是否存在
         if(typeof onRejected !== 'function'){
             onRejected = reason =>{
                 throw reason;
             }
         }
         if(typeof onResolved !== 'function'){
             onResolved = value => value;
         }
            return new Promise((resolve, reject) => {
                //封裝重復的部分
                function callback(type){
                    try {
                        //將結果值傳入
                        let result = type(that.PromiseResult);
                        //判斷
                        if (result instanceof Promise) {
                            //如果是Promise物件
                            result.then(v => {
                                resolve(v);
                            }, r => {
                                reject(r);
                            })
                        } else {
                            //結果物件狀態為【成功】
                            resolve(result);
                        }
                    } catch (e) {
                        reject(e);
                    }
                }
                //如果Promise狀態為fulfilled回呼這個函式
                if (this.PromiseState === 'fulfilled') {
                    callback(onResolved);
                }
                //如果Promise狀態為rejected回呼這個函式
                if (this.PromiseState === 'rejected') {
                    callback(onRejected);
                }
                //如果Promise狀態為pending,保存回呼函式
                if (this.PromiseState === 'pending') {
                    this.callbacks.push({
                        onResolved: function () {
                            callback(onResolved);
                        },
                        onRejected: function () {
                            callback(onRejected);
                        }
                    })
                }
            })
        }
//添加catch 方法
     Promise.prototype.catch = function(onRejected){
         return this.then(undefined,onRejected);
     }

注:typeof 運算子回傳一個字串,表示未經計算的運算元的型別,

13. 封裝Promise.resolve()方法:
// 自定義函式Promise
function Promise(executor){
          //添加狀態屬性與結果值屬性
          this.PromiseState = 'pending';
          this.PromiseResult = null;
          // 定義callback屬性,保存pending狀態的回呼函式
          this.callbacks = [];
           //保存實體物件的this值
           const that = this;
          //自定義resolve函式,名字不一定用resolve
          function resolve(data){
            //判斷狀態是否修改過
            if(that.PromiseState !== 'pending') return;
             //改變狀態屬性
             that.PromiseState = 'fulfilled';  // 或者 resolve 
             //改變結果值屬性
             that.PromiseResult =data;
              //異步任務成功后執行回呼函式
              that.callbacks.forEach(item=>{
                  item.onResolved(data);
              })
          }
          //自定義reject函式
          function reject(data){
             //判斷狀態是否修改過,改過就直接回傳
            if(that.PromiseState !== 'pending') return;
              //改變狀態屬性
             that.PromiseState = 'rejected';  
            //改變結果值屬性
             that.PromiseResult =data;
             //異步任務失敗后執行回呼函式
            that.callbacks.forEach(item=>{
                item.onRejected(data);
            })
          }

          try{
          //同步呼叫【執行器函式】
          executor(resolve,reject);
          }catch(e){
              //更改Promise物件為失敗
              reject(e);
          }
          
     }
     // 添加then方法
     Promise.prototype.then = function (onResolved, onRejected) {
         const that = this;
         //判斷回呼引數是否存在
         if(typeof onRejected !== 'function'){
             onRejected = reason =>{
                 throw reason;
             }
         }
         if(typeof onResolved !== 'function'){
             onResolved = value => value;
         }
            return new Promise((resolve, reject) => {
                //封裝重復的部分
                function callback(type){
                    try {
                        //將結果值傳入
                        let result = type(that.PromiseResult);
                        //判斷
                        if (result instanceof Promise) {
                            //如果是Promise物件
                            result.then(v => {
                                resolve(v);
                            }, r => {
                                reject(r);
                            })
                        } else {
                            //結果物件狀態為【成功】
                            resolve(result);
                        }
                    } catch (e) {
                        reject(e);
                    }
                }
                //如果Promise狀態為fulfilled回呼這個函式
                if (this.PromiseState === 'fulfilled') {
                    callback(onResolved);
                }
                //如果Promise狀態為rejected回呼這個函式
                if (this.PromiseState === 'rejected') {
                    callback(onRejected);
                }
                //如果Promise狀態為pending,保存回呼函式
                if (this.PromiseState === 'pending') {
                    this.callbacks.push({
                        onResolved: function () {
                            callback(onResolved);
                        },
                        onRejected: function () {
                            callback(onRejected);
                        }
                    })
                }
            })
        }
//添加catch 方法
     Promise.prototype.catch = function(onRejected){
         return this.then(undefined,onRejected);
     }
//添加resolve方法
Promise.resolve = function(value){
    //回傳promise物件
    return new Promise((resolve,reject) =>{
       if(value instanceof Promise){
            value.then(v=>{
               resolve(v);
            },r=>{
               reject(r);
            })
       }else{
            resolve(value);
       }
    })
}

注:instanceof 運算子用于檢測建構式的 prototype 屬性是否出現在某個實體物件的原型鏈上,
實踐一下:

 let p = Promise.resolve(new Promise((resolve,reject)=>{
          reject('_(′?`」 ∠)_');
      }));
      console.log(p);

結果:
在這里插入圖片描述

14. 封裝Promise.reject方法:

無論傳入啥只回傳一個失敗的promise物件,

// 自定義函式Promise
function Promise(executor){
          //添加狀態屬性與結果值屬性
          this.PromiseState = 'pending';
          this.PromiseResult = null;
          // 定義callback屬性,保存pending狀態的回呼函式
          this.callbacks = [];
           //保存實體物件的this值
           const that = this;
          //自定義resolve函式,名字不一定用resolve
          function resolve(data){
            //判斷狀態是否修改過
            if(that.PromiseState !== 'pending') return;
             //改變狀態屬性
             that.PromiseState = 'fulfilled';  // 或者 resolve 
             //改變結果值屬性
             that.PromiseResult =data;
              //異步任務成功后執行回呼函式
              that.callbacks.forEach(item=>{
                  item.onResolved(data);
              })
          }
          //自定義reject函式
          function reject(data){
             //判斷狀態是否修改過,改過就直接回傳
            if(that.PromiseState !== 'pending') return;
              //改變狀態屬性
             that.PromiseState = 'rejected';  
            //改變結果值屬性
             that.PromiseResult =data;
             //異步任務失敗后執行回呼函式
            that.callbacks.forEach(item=>{
                item.onRejected(data);
            })
          }

          try{
          //同步呼叫【執行器函式】
          executor(resolve,reject);
          }catch(e){
              //更改Promise物件為失敗
              reject(e);
          }
          
     }
     // 添加then方法
     Promise.prototype.then = function (onResolved, onRejected) {
         const that = this;
         //判斷回呼引數是否存在
         if(typeof onRejected !== 'function'){
             onRejected = reason =>{
                 throw reason;
             }
         }
         if(typeof onResolved !== 'function'){
             onResolved = value => value;
         }
            return new Promise((resolve, reject) => {
                //封裝重復的部分
                function callback(type){
                    try {
                        //將結果值傳入
                        let result = type(that.PromiseResult);
                        //判斷
                        if (result instanceof Promise) {
                            //如果是Promise物件
                            result.then(v => {
                                resolve(v);
                            }, r => {
                                reject(r);
                            })
                        } else {
                            //結果物件狀態為【成功】
                            resolve(result);
                        }
                    } catch (e) {
                        reject(e);
                    }
                }
                //如果Promise狀態為fulfilled回呼這個函式
                if (this.PromiseState === 'fulfilled') {
                    callback(onResolved);
                }
                //如果Promise狀態為rejected回呼這個函式
                if (this.PromiseState === 'rejected') {
                    callback(onRejected);
                }
                //如果Promise狀態為pending,保存回呼函式
                if (this.PromiseState === 'pending') {
                    this.callbacks.push({
                        onResolved: function () {
                            callback(onResolved);
                        },
                        onRejected: function () {
                            callback(onRejected);
                        }
                    })
                }
            })
        }
//添加catch 方法
     Promise.prototype.catch = function(onRejected){
         return this.then(undefined,onRejected);
     }
//添加resolve方法
Promise.resolve = function(value){
    //回傳promise物件
    return new Promise((resolve,reject) =>{
       if(value instanceof Promise){
            value.then(v=>{
               resolve(v);
            },r=>{
               reject(r);
            })
       }else{
            resolve(value);
       }
    })
}
//添加reject方法
Promise.reject = function(reason){
    return new Promise((resolve,reject)=>{
        reject(reason);
    });
}
15. 封裝Promise.all方法:

回傳一個新的promise,只有所有的promise都成功才成功,只要有一個失敗了就直接失敗,失敗了回傳那個失敗值,

// 自定義函式Promise
function Promise(executor){
          //添加狀態屬性與結果值屬性
          this.PromiseState = 'pending';
          this.PromiseResult = null;
          // 定義callback屬性,保存pending狀態的回呼函式
          this.callbacks = [];
           //保存實體物件的this值
           const that = this;
          //自定義resolve函式,名字不一定用resolve
          function resolve(data){
            //判斷狀態是否修改過
            if(that.PromiseState !== 'pending') return;
             //改變狀態屬性
             that.PromiseState = 'fulfilled';  // 或者 resolve 
             //改變結果值屬性
             that.PromiseResult =data;
              //異步任務成功后執行回呼函式
              that.callbacks.forEach(item=>{
                  item.onResolved(data);
              })
          }
          //自定義reject函式
          function reject(data){
             //判斷狀態是否修改過,改過就直接回傳
            if(that.PromiseState !== 'pending') return;
              //改變狀態屬性
             that.PromiseState = 'rejected';  
            //改變結果值屬性
             that.PromiseResult =data;
             //異步任務失敗后執行回呼函式
            that.callbacks.forEach(item=>{
                item.onRejected(data);
            })
          }

          try{
          //同步呼叫【執行器函式】
          executor(resolve,reject);
          }catch(e){
              //更改Promise物件為失敗
              reject(e);
          }
          
     }
     // 添加then方法
     Promise.prototype.then = function (onResolved, onRejected) {
         const that = this;
         //判斷回呼引數是否存在
         if(typeof onRejected !== 'function'){
             onRejected = reason =>{
                 throw reason;
             }
         }
         if(typeof onResolved !== 'function'){
             onResolved = value => value;
         }
            return new Promise((resolve, reject) => {
                //封裝重復的部分
                function callback(type){
                    try {
                        //將結果值傳入
                        let result = type(that.PromiseResult);
                        //判斷
                        if (result instanceof Promise) {
                            //如果是Promise物件
                            result.then(v => {
                                resolve(v);
                            }, r => {
                                reject(r);
                            })
                        } else {
                            //結果物件狀態為【成功】
                            resolve(result);
                        }
                    } catch (e) {
                        reject(e);
                    }
                }
                //如果Promise狀態為fulfilled回呼這個函式
                if (this.PromiseState === 'fulfilled') {
                    callback(onResolved);
                }
                //如果Promise狀態為rejected回呼這個函式
                if (this.PromiseState === 'rejected') {
                    callback(onRejected);
                }
                //如果Promise狀態為pending,保存回呼函式
                if (this.PromiseState === 'pending') {
                    this.callbacks.push({
                        onResolved: function () {
                            callback(onResolved);
                        },
                        onRejected: function () {
                            callback(onRejected);
                        }
                    })
                }
            })
        }
//添加catch 方法
     Promise.prototype.catch = function(onRejected){
         return this.then(undefined,onRejected);
     }
//添加resolve方法
Promise.resolve = function(value){
    //回傳promise物件
    return new Promise((resolve,reject) =>{
       if(value instanceof Promise){
            value.then(v=>{
               resolve(v);
            },r=>{
               reject(r);
            })
       }else{
            resolve(value);
       }
    })
}
//添加reject方法
Promise.reject = function(reason){
    return new Promise((resolve,reject)=>{
        reject(reason);
    });
}
//添加all方法
Promise.all = function(promises){
    return new Promise((resolve,reject) => {
        //添加變數
        let count = 0;
        // 存放成功結果陣列
        let arr =[];
        //遍歷全部
        for (let i = 0; i < promises.length; i++) {
            promises[i].then(v => {
                //能進到證明其為成功
                count++;
                //保存成功結果
                arr[i]=v;
                //如果全部成功
                if (count === promises.length) {
                    //狀態為成功
                    resolve(arr);
                }
            }, r => {
                 //能進到證明其為失敗
                reject(r);
            });
        }
    });
}

試一下:

 let p1 = new Promise((resolve,reject)=>{
          resolve('_(′?`」 ∠)_');
      });
      let p2 = Promise.resolve('ok');
      let p3 = Promise.resolve('yes');
      let res = Promise.all([p1,p2,p3]);
      console.log(res);

結果:
在這里插入圖片描述

16. 封裝Promise.race方法:

回傳一個新的promise,第一個完成的promise的結果狀態改變的就是最終的結果狀態,
上面重復的代碼就不寫上了:

//添加race方法
Promise.race = function(promises){
    return new Promise((resolve,reject) => {
        //遍歷全部
        for (let i = 0; i < promises.length; i++) {
            promises[i].then(v => {
                    //能進到證明其為成功
                    //狀態為成功
                    resolve(v);
                }, r => {
                 //能進到證明其為失敗
                reject(r);
            })
         }
      });
    }

試一下:

 let p1 = new Promise((resolve,reject)=>{
          setTimeout(()=>{
            resolve('_(′?`」 ∠)_');
          })
         
      });
      let p2 = Promise.resolve('ok');
      let p3 = Promise.resolve('yes');
      let res = Promise.race([p1,p2,p3]);
      console.log(res);

沒毛病:
在這里插入圖片描述

17.回呼函式異步執行:

上面回呼函式還是同步執行的,要讓 then()回呼函式異步執行,
添加定時器模仿異步操作:

// 自定義函式Promise
function Promise(executor){
          //添加狀態屬性與結果值屬性
          this.PromiseState = 'pending';
          this.PromiseResult = null;
          // 定義callback屬性,保存pending狀態的回呼函式
          this.callbacks = [];
           //保存實體物件的this值
           const that = this;
          //自定義resolve函式,名字不一定用resolve
          function resolve(data) {
        //判斷狀態是否修改過
        if (that.PromiseState !== 'pending') return;
        //改變狀態屬性
        that.PromiseState = 'fulfilled';  // 或者 resolve 
        //改變結果值屬性
        that.PromiseResult = data;
        //異步任務成功后執行回呼函式
        setTimeout(() => {
            that.callbacks.forEach(item => {
                item.onResolved(data);
            })
        });
    }
    //自定義reject函式
    function reject(data) {
        //判斷狀態是否修改過,改過就直接回傳
        if (that.PromiseState !== 'pending') return;
        //改變狀態屬性
        that.PromiseState = 'rejected';
        //改變結果值屬性
        that.PromiseResult = data;
        //異步任務失敗后執行回呼函式
        setTimeout(() => {
            that.callbacks.forEach(item => {
                item.onRejected(data);
            })
        });
    }

          try{
          //同步呼叫【執行器函式】
          executor(resolve,reject);
          }catch(e){
              //更改Promise物件為失敗
              reject(e);
          }
          
     }
     // 添加then方法
     Promise.prototype.then = function (onResolved, onRejected) {
         const that = this;
         //判斷回呼引數是否存在
         if(typeof onRejected !== 'function'){
             onRejected = reason =>{
                 throw reason;
             }
         }
         if(typeof onResolved !== 'function'){
             onResolved = value => value;
         }
            return new Promise((resolve, reject) => {
                //封裝重復的部分
                function callback(type){
                    try {
                        //將結果值傳入
                        let result = type(that.PromiseResult);
                        //判斷
                        if (result instanceof Promise) {
                            //如果是Promise物件
                            result.then(v => {
                                resolve(v);
                            }, r => {
                                reject(r);
                            })
                        } else {
                            //結果物件狀態為【成功】
                            resolve(result);
                        }
                    } catch (e) {
                        reject(e);
                    }
                }
                //如果Promise狀態為fulfilled回呼這個函式
                if (this.PromiseState === 'fulfilled') {
                    setTimeout(()=>{
                        callback(onResolved);
                    });
                }
                //如果Promise狀態為rejected回呼這個函式
                if (this.PromiseState === 'rejected') {
                    setTimeout(()=>{
                        callback(onRejected);
                    });
                }
                //如果Promise狀態為pending,保存回呼函式
                if (this.PromiseState === 'pending') {
                    this.callbacks.push({
                        onResolved: function () {
                            callback(onResolved);
                        },
                        onRejected: function () {
                            callback(onRejected);
                        }
                    })
                }
            })
        }
//添加catch 方法
     Promise.prototype.catch = function(onRejected){
         return this.then(undefined,onRejected);
     }
//添加resolve方法
Promise.resolve = function(value){
    //回傳promise物件
    return new Promise((resolve,reject) =>{
       if(value instanceof Promise){
            value.then(v=>{
               resolve(v);
            },r=>{
               reject(r);
            })
       }else{
            resolve(value);
       }
    })
}
//添加reject方法
Promise.reject = function(reason){
    return new Promise((resolve,reject)=>{
        reject(reason);
    });
}
//添加all方法
Promise.all = function(promises){
    return new Promise((resolve,reject) => {
        //添加變數
        let count = 0;
        // 存放成功結果陣列
        let arr =[];
        //遍歷全部
        for (let i = 0; i < promises.length; i++) {
            promises[i].then(v => {
                //能進到證明其為成功
                count++;
                //保存成功結果
                arr[i]=v;
                //如果全部成功
                if (count === promises.length) {
                    //狀態為成功
                    resolve(arr);
                }
            }, r => {
                 //能進到證明其為失敗
                reject(r);
            });
        }
    });
}
//添加race方法
Promise.race = function(promises){
    return new Promise((resolve,reject) => {
        //遍歷全部
        for (let i = 0; i < promises.length; i++) {
            promises[i].then(v => {
                    //能進到證明其為成功
                    //狀態為成功
                    resolve(v);
                }, r => {
                 //能進到證明其為失敗
                reject(r);
            })
         }
      });
    }
18.class版本封裝:

最終封裝:

class Promise{
    //構造方法
    constructor(executor) {
          //添加狀態屬性與結果值屬性
          this.PromiseState = 'pending';
          this.PromiseResult = null;
          // 定義callback屬性,保存pending狀態的回呼函式
          this.callbacks = [];
           //保存實體物件的this值
           const that = this;
          //自定義resolve函式,名字不一定用resolve
          function resolve(data) {
        //判斷狀態是否修改過
        if (that.PromiseState !== 'pending') return;
        //改變狀態屬性
        that.PromiseState = 'fulfilled';  // 或者 resolve 
        //改變結果值屬性
        that.PromiseResult = data;
        //異步任務成功后執行回呼函式
        setTimeout(() => {
            that.callbacks.forEach(item => {
                item.onResolved(data);
            })
        });
    }
    //自定義reject函式
    function reject(data) {
        //判斷狀態是否修改過,改過就直接回傳
        if (that.PromiseState !== 'pending') return;
        //改變狀態屬性
        that.PromiseState = 'rejected';
        //改變結果值屬性
        that.PromiseResult = data;
        //異步任務失敗后執行回呼函式
        setTimeout(() => {
            that.callbacks.forEach(item => {
                item.onRejected(data);
            })
        });
    }

          try{
          //同步呼叫【執行器函式】
          executor(resolve,reject);
          }catch(e){
              //更改Promise物件為失敗
              reject(e);
          }
    }
    //then方法封裝
    then(onResolved,onRejected){
        const that = this;
         //判斷回呼引數是否存在
         if(typeof onRejected !== 'function'){
             onRejected = reason =>{
                 throw reason;
             }
         }
         if(typeof onResolved !== 'function'){
             onResolved = value => value;
         }
            return new Promise((resolve, reject) => {
                //封裝重復的部分
                function callback(type){
                    try {
                        //將結果值傳入
                        let result = type(that.PromiseResult);
                        //判斷
                        if (result instanceof Promise) {
                            //如果是Promise物件
                            result.then(v => {
                                resolve(v);
                            }, r => {
                                reject(r);
                            })
                        } else {
                            //結果物件狀態為【成功】
                            resolve(result);
                        }
                    } catch (e) {
                        reject(e);
                    }
                }
                //如果Promise狀態為fulfilled回呼這個函式
                if (this.PromiseState === 'fulfilled') {
                    setTimeout(()=>{
                        callback(onResolved);
                    });
                }
                //如果Promise狀態為rejected回呼這個函式
                if (this.PromiseState === 'rejected') {
                    setTimeout(()=>{
                        callback(onRejected);
                    });
                }
                //如果Promise狀態為pending,保存回呼函式
                if (this.PromiseState === 'pending') {
                    this.callbacks.push({
                        onResolved: function () {
                            callback(onResolved);
                        },
                        onRejected: function () {
                            callback(onRejected);
                        }
                    })
                }
            })
    }
    //catch 方法
    catch(onRejected){
         return this.then(undefined,onRejected);
     }
    //resolve方法
    static resolve(value){
    //回傳promise物件
    return new Promise((resolve,reject) =>{
       if(value instanceof Promise){
            value.then(v=>{
               resolve(v);
            },r=>{
               reject(r);
            })
       }else{
            resolve(value);
       }
    })
}
    //reject方法
    static reject(reason){
    return new Promise((resolve,reject)=>{
        reject(reason);
    });
}
    //all方法
    static all(promises) {
        return new Promise((resolve, reject) => {
            //添加變數
            let count = 0;
            // 存放成功結果陣列
            let arr = [];
            //遍歷全部
            for (let i = 0; i < promises.length; i++) {
                promises[i].then(v => {
                    //能進到證明其為成功
                    count++;
                    //保存成功結果
                    arr[i] = v;
                    //如果全部成功
                    if (count === promises.length) {
                        //狀態為成功
                        resolve(arr);
                    }
                }, r => {
                    //能進到證明其為失敗
                    reject(r);
                });
            }
        });
    }
    //race方法
    static race(promises) {
        return new Promise((resolve, reject) => {
            //遍歷全部
            for (let i = 0; i < promises.length; i++) {
                promises[i].then(v => {
                    //能進到證明其為成功
                    //狀態為成功
                    resolve(v);
                }, r => {
                    //能進到證明其為失敗
                    reject(r);
                })
            }
        });
    }

}

十一:async函式:

MDN檔案

1.函式的回傳值為promise物件,
2.promise物件的結果由async函式執行的回傳值決定,
3.其實跟 then()方法回傳結果是一樣一樣的,

1.回傳一個非Promise物件,回傳值是resolve,
 async function main(){
             return '123';
          }
          let res = main();
          console.log(res);

在這里插入圖片描述

2.如果回傳是一個Promise物件,由回傳結果決定:

如:

 async function main(){
             return new Promise((resolve,reject)=>{
                 reject('NO');
             });
          }
          let res = main();
          console.log(res);

在這里插入圖片描述

3.拋出例外也是失敗:
 async function main(){
             return new Promise((resolve,reject)=>{
                 reject('NO');
             });
          }
          let res = main();
          console.log(res);

在這里插入圖片描述

十二.await運算式:

MDN檔案

1.await右側的運算式一般為promise物件,但也可以是其它的值,
2.如果運算式是promise物件,await回傳的是promise成功的值,
3.如果運算式是其它值,直接將此值作為await的回傳值,

注意:

1.await 必須寫在async函式中,但async 函式中可以沒有await ,
2.如果await的promise失敗了,就會拋出例外,需要通過try…catch捕獲處理,

1.右側為promise物件:
 async function works(){
             let p = new Promise((resolve,reject)=>{
                 resolve('oh yes')
             })
             let res = await p;
             console.log(res);
         }
         works();

結果:
oh yes

2.右側為其它值:
  async function works(){
             let p = new Promise((resolve,reject)=>{
                 resolve('oh yes')
             })
           //  let res = await p;
           let res = await 100;
             console.log(res);
         }
         works();

結果:
100

3.如果promise是失敗狀態:
 async function works(){
             let p = new Promise((resolve,reject)=>{
                // resolve('oh yes')
                reject('err');
             })          
            try{
                let res = await p;
            }catch(e){
                console.log(e);
            }
         }
         works();

在這里插入圖片描述

十三.async與await結合發生ajax請求:

效果: 點擊按鈕獲取一句名言,

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button id="btn">獲取一句名言</button>
    <script>
        function sendAJAX(url) {
         return new Promise((resolve, reject) => {
                //創建物件
                const xhr = new XMLHttpRequest();
                xhr.responseType = 'json';
                //初始化
                xhr.open('GET', url);
                //發送
                xhr.send();
                //處理回應結果
                xhr.onreadystatechange = function () {
                    if (xhr.readyState === 4) {
                        if (xhr.status >= 200 && xhr.status < 300) {
                            //輸出回應體
                            resolve(xhr.response);
                        } else {
                            //輸出回應狀態碼
                            reject(xhr.status);
                        }
                    }
                }
            });
     }
         
        var btn = document.querySelector("#btn");
        btn.addEventListener('click',async function(){
             let word = await sendAJAX("http://poetry.apiopen.top/sentences");
              console.log(word);
        })
    </script>
</body>
</html>

在這里插入圖片描述

十四.總結:

我只想說…
在這里插入圖片描述

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/276986.html

標籤:其他

上一篇:C/C++學習的準備作業

下一篇:C語言-7(學習C語言的第七天)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more