中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

利用ES6進行Promise封裝的案例

發布時間:2021-02-05 11:47:33 來源:億速云 閱讀:290 作者:小新 欄目:web開發

這篇文章主要介紹了利用ES6進行Promise封裝的案例,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

原生Promise解析

簡介

promise是異步編程的一種解決方案,比傳統的解決方案--回調函數和事件--更合理和強大。

promise簡單說就是一個容器,里面保存著某個未來才會結束的事件(通常是一個異步操作)的結果,從語法上來說,Promise是一個對象,從它可以獲取異步操作的消息,Promise提供統一的API,各種異步操作都可以用同樣的方法進行處理

特點

對象的狀態不受外界影響,Promise對象代表一個異步操作,有三種狀態:Pendding、fulfilled、rejected。只有異步操作的結果,可以決定當前是哪一種狀態,其他操作都無法改變這個狀態。

一旦狀態改變,就不會在變,任何時候都可以得到這個結果,只有兩種可能:從Pendding變為fulfilled和從Pendding變為rejected。只要這兩種情況發生,狀態就凝固了,會一直保持這個結果,這時就稱為resolved。

利用es6進行Promise封裝

處理同步任務

原生方法調用方式

  new Promise((resolve,reject)=>{
    resolve(1)
  }).then(res=>{
    console.log(res) //1
  })

同步封裝思考

1.由調用方式可見Promise是一個類
2.它接收一個回調函數,這個回調函數接受resolve和reject方法作為參數
3.當狀態改變后執行then方法,并將resolve或reject的結果作為then方法接受回調函數的參數

  class Mypromise{
    constructor(callback){
      this.status='pendding'
      //成功結果
      this.s_res = null
      // 失敗結果
      this.f_res = null
      callback((arg)=>{ // 使用箭頭函數this不會丟失
       // 改變狀態為成功
       this.status = 'fulfilled'
       this.s_res = arg
      },(arg)=>{
        // 改變狀態為失敗
        this.status = 'rejected'
        this.f_res = arg 
      })
    }
    then(onresolve,onreject){
      if(this.status === 'fulfilled'){ // 當狀態為成功時
        onresolve(this.s_res)
      }else if(this.status === 'rejected'){ // 當狀態為失敗時
        onreject(this.f_res)
      }
    }
  }

處理異步任務

原生調用方式

  new Promise((resolve,reject)=>{
    setTimeOut(()=>{
      resolve(1)
    },1000)
  }).then(res=>{
    console.log(res)
  })

異步封裝思考

1.根據js執行機制,setTimeOut屬于宏任務,then回調函數屬于微任務,當主線程執行完成后,會從異步隊列中取出本次的微任務先執行。

2.也就是說,then方法執行時,狀態還沒有改變,所有我們需要將then方法執行的回調保存起來,等到異步代碼執行完成后,在統一執行then方法的回調函數

  class Mypromise{
    constructor(callback){
      this.status='pendding'
      //成功結果
      this.s_res = null
      // 失敗結果
      this.f_res = null
      this.query = [] // ++ 
      callback((arg)=>{ // 使用箭頭函數this不會丟失
       // 改變狀態為成功
       this.status = 'fulfilled'
       this.s_res = arg
       // 當狀態改變后,統一執行then方法的回調
       this.query.forEach(item=>{
         item.resolve(arg)
       })
      },(arg)=>{
        // 改變狀態為失敗
        this.status = 'rejected'
        this.f_res = arg 
        // 當狀態改變后,統一執行then方法的回調
       this.query.forEach(item=>{
         item.reject(arg)
       })
      })
    }
    then(onresolve,onreject){
      if(this.status === 'fulfilled'){ // 當狀態為成功時
        onresolve(this.s_res)
      }else if(this.status === 'rejected'){ // 當狀態為失敗時
        onreject(this.f_res)
      }else{ // ++ 狀態沒有改變
        this.query.push({ // 保存回調函數到隊列中
          resolve:onresolve,
          reject:onreject
        })
      }
    }
  }

處理鏈式調用

原生調用方式

  new Promise((resolve,reject)=>{
    resolve(1)
  }).then(res=>{
    return res
  }).then(res=>{
    console.log(res)
  })

鏈式調用思考

原生的Promise對象的then方法,返回的也是一個Promise對象,一個新的Promise才能支持鏈式調用

下一個then方法可以接受上一個then方法的返回值作為回調函數的參數

主要考慮上一個then方法的返回值:

1.Promise對象/具有then方法的對象

2.其他值

第一個then方法返回一個Promise對象,它的回調函數接受resFn和rejFN兩個回調函數作為參數,把成功狀態的處理封裝為handle函數,接受成功的結果作為參數

在handle函數,根據onresolve返回值的不同做出不同的處理

  class Mypromise{
    constructor(callback){
      this.status='pendding'
      //成功結果
      this.s_res = null
      // 失敗結果
      this.f_res = null
      this.query = [] // ++ 
      callback((arg)=>{ // 使用箭頭函數this不會丟失
       // 改變狀態為成功
       this.status = 'fulfilled'
       this.s_res = arg
       // 當狀態改變后,統一執行then方法的回調
       this.query.forEach(item=>{
         item.resolve(arg)
       })
      },(arg)=>{
        // 改變狀態為失敗
        this.status = 'rejected'
        this.f_res = arg 
        // 當狀態改變后,統一執行then方法的回調
       this.query.forEach(item=>{
         item.reject(arg)
       })
      })
    }
    then(onresolve,onreject){
      return new Mypromise((resFN,rejFN)=>{
        if(this.status === 'fulfilled'){ // 當狀態為成功時
          handle(this.s_res)
        }else if(this.status === 'rejected'){ // 當狀態為失敗時
          errBack(this.f_res)
        }else{ // ++ 狀態沒有改變
          this.query.push({ // 保存回調函數到隊列中
            resolve:onresolve,
            reject:onreject
          })
        } 
        function handle(value){
          // 當then方法的onresolve方法有返回值時,保存其返回值,沒有使用其保存的值
          let returnVal = onresolve instanceof Function && onresolve(value) || value
          // 如果onresolve方法返回的是promise對象,則調用其then方法
          if(returnVal&&returnVal['then'] instanceof Function){
            returnVal.then(res=>{
              resFN(res)
            },err=>{
              rejFN(err)
            })
          }else{
            resFN(returnVal)
          } 
        }
        function errBack(reason){
          if(onreject instanceof Function){
            let returnVal = reject(reason)
            if(typeof returnVal !== 'undenfined' && returnVal['then'] instanceof Function){
              returnVal.then(res=>{
                resFN(res)
              },err=>{
                rejFN(err)
              })
            }else{
              resFN(returnVal)
            }
          }else{
            rejFN(reason)
          }
        }
      })
    }
  }

Promise.all和Promise.race方法

原生調用方式

Promise.all方法接受一個數組,數組中的每一項都是一個Promise實例,只有數組中的所有Promise實例的狀態都變為fulfilled時,此時整個狀態才會變成fulfilled,此時數組中所有Promise實例的返回值組成一個新的數組,進行傳遞。

Promise.race方法和Promise.all方法一樣,如果不是Promise實例,就會先調用Promise.resolve方法,將參數轉為Promise實例,在進行下一步處理。

只要數組中有一個參數的狀態變為fulfilled就會進行傳遞

// 將現有對象轉換為Promise對象
  Mypromise.resolve = (arg)=>{
    if(typeof arg == 'undefined' || arg==null){ // 不帶有任何參數
      return new Mypromise(resolve=>{
        resolve(arg)
      })
    }else if(arg instanceof Mypromise){ // 是一個Mypromise實例
      return arg
    }else if(arg['then'] instanceof Function){ // 具有then方法的對象
      return new Mypromise((resolve,reject)=>{
        arg.then(res=>{
          resolve(res)
        },err=>{
          reject(err)
        })
      })
    }else{ // 參數不是具有then方法的對象,或根本不是對象
      return new Mypromise(resolve=>{
        resolve(arg)
      }) 
    }
  }
  Mypromise.all = (arr)=>{
    if(!Array.isArray(arr)){
      throw new TypeError('參數必須是一個數組')
    }
    return new Mypromise((resolve,reject)=>{
      let i=0,result=[]
      next()
      functon next(){
        // 如果不是Mypromise實例需要轉換
        Mypromise.resolve(arr[i]).then(res=>{
          result.push(res)
          i++
          if(i===arr.length){
            resolve(result)
          }else{
            next()
          }
        },reject)
      }
    })
  }
  Mypromise.race = (arr)=>{
    if(!Array.isArray(arr)){
      throw new TypeError('參數必須是一個數組')
    }
    return new Mypromise((resolve,reject)=>{
      let done = false
      arr.forEach(item=>{
        Mypromise.resolve(item).then(res=>{
          if(!done){
            resolve(res)
            done = true
          }
        },err=>{
          if(!done){
            reject(res)
            done = true
          }
        })
      })
    })
  }

處理Mypromise狀態確定不能改變的特性

在重寫callback中的resolve和reject方法執行前,先判斷狀態是否為'pendding'

感謝你能夠認真閱讀完這篇文章,希望小編分享的“利用ES6進行Promise封裝的案例”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

南陵县| 新晃| 吉安县| 伊川县| 任丘市| 松江区| 湖州市| 靖宇县| 曲沃县| 襄汾县| 潮安县| 大冶市| 大埔县| 镇江市| 洱源县| 嘉兴市| 麻栗坡县| 禹城市| 巴马| 平阴县| 台北市| 迁安市| 宜阳县| 保康县| 宕昌县| 新竹市| 乌拉特前旗| 资源县| 仲巴县| 布尔津县| 苏州市| 无为县| 舟山市| 阿城市| 克东县| 肥乡县| 海兴县| 青川县| 潍坊市| 柳林县| 六枝特区|