深度解析利用ES6進行Promise封裝總結

這篇文章主要介紹瞭如何利用ES6進行Promise封裝總結,文中經過示例代碼介紹的很是詳細,寫的十分的全面細緻,具備必定的參考價值,對此有須要的朋友能夠參考學習下。若有不足之處,歡迎批評指正。前端

原生Promise解析es6

簡介編程

  • promise是異步編程的一種解決方案,比傳統的解決方案--回調函數和事件--更合理和強大。
  • promise簡單說就是一個容器,裏面保存着某個將來纔會結束的事件(一般是一個異步操做)的結果,從語法上來講,Promise是一個對象,從它能夠獲取異步操做的消息,Promise提供統一的API,各類異步操做均可以用一樣的方法進行處理

特色數組

對象的狀態不受外界影響,Promise對象表明一個異步操做,有三種狀態:Pendding、fulfilled、rejected。只有異步操做的結果,能夠決定當前是哪種狀態,其餘操做都沒法改變這個狀態。 一旦狀態改變,就不會在變,任什麼時候候均可以獲得這個結果,只有兩種可能:從Pendding變爲fulfilled和從Pendding變爲rejected。只要這兩種狀況發生,狀態就凝固了,會一直保持這個結果,這時就稱爲resolved。 1.利用es6進行Promise封裝promise

2.處理同步任務異步

3.原生方法調用方式異步編程

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)
    }//在此我向你們推薦一個前端全棧開發交流圈:619586920  突破技術瓶頸,提高思惟能力
  }
}

處理異步任務學習

原生調用方式this

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)
     })//在此我向你們推薦一個前端全棧開發交流圈:619586920  突破技術瓶頸,提高思惟能力
    },(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
      })//在此我向你們推薦一個前端全棧開發交流圈:619586920  突破技術瓶頸,提高思惟能力
    }
  }
}

處理鏈式調用

原生調用方式

new Promise((resolve,reject)=>{
  resolve(1)
}).then(res=>{
  return res
}).then(res=>{
  console.log(res)
})//在此我向你們推薦一個前端全棧開發交流圈:619586920  突破技術瓶頸,提高思惟能力

鏈式調用思考

原生的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
        })
      } //在此我向你們推薦一個前端全棧開發交流圈:619586920  突破技術瓶頸,提高思惟能力
      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)
        })//在此我向你們推薦一個前端全棧開發交流圈:619586920  突破技術瓶頸,提高思惟能力
      })
    }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)
      }
    })
  }//在此我向你們推薦一個前端全棧開發交流圈:619586920  突破技術瓶頸,提高思惟能力
  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'

結語

感謝您的觀看,若有不足之處,歡迎批評指正。

相關文章
相關標籤/搜索