這篇文章主要介紹瞭如何利用ES6進行Promise封裝總結,文中經過示例代碼介紹的很是詳細,寫的十分的全面細緻,具備必定的參考價值,對此有須要的朋友能夠參考學習下。若有不足之處,歡迎批評指正。前端
原生Promise解析es6
簡介編程
特色數組
對象的狀態不受外界影響,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'
結語
感謝您的觀看,若有不足之處,歡迎批評指正。