這篇文章主要介紹了如何利用ES6進(jìn)行Promise封裝總結(jié),文中通過(guò)示例代碼介紹的非常詳細(xì),寫的十分的全面細(xì)致,具有一定的參考價(jià)值,對(duì)此有需要的朋友可以參考學(xué)習(xí)下。如有不足之處,歡迎批評(píng)指正。
原生Promise解析
簡(jiǎn)介
promise是異步編程的一種解決方案,比傳統(tǒng)的解決方案--回調(diào)函數(shù)和事件--更合理和強(qiáng)大。 promise簡(jiǎn)單說(shuō)就是一個(gè)容器,里面保存著某個(gè)未來(lái)才會(huì)結(jié)束的事件(通常是一個(gè)異步操作)的結(jié)果,從語(yǔ)法上來(lái)說(shuō),Promise是一個(gè)對(duì)象,從它可以獲取異步操作的消息,Promise提供統(tǒng)一的API,各種異步操作都可以用同樣的方法進(jìn)行處理 特點(diǎn)
對(duì)象的狀態(tài)不受外界影響,Promise對(duì)象代表一個(gè)異步操作,有三種狀態(tài):Pendding、fulfilled、rejected。只有異步操作的結(jié)果,可以決定當(dāng)前是哪一種狀態(tài),其他操作都無(wú)法改變這個(gè)狀態(tài)。 一旦狀態(tài)改變,就不會(huì)在變,任何時(shí)候都可以得到這個(gè)結(jié)果,只有兩種可能:從Pendding變?yōu)閒ulfilled和從Pendding變?yōu)閞ejected。只要這兩種情況發(fā)生,狀態(tài)就凝固了,會(huì)一直保持這個(gè)結(jié)果,這時(shí)就稱為resolved。 1.利用es6進(jìn)行Promise封裝
2.處理同步任務(wù)
3.原生方法調(diào)用方式
new Promise((resolve,reject)=>{resolve(1)
}).then(res=>{console.log(res) //1
})
同步封裝思考 1.由調(diào)用方式可見(jiàn)Promise是一個(gè)類 2.它接收一個(gè)回調(diào)函數(shù),這個(gè)回調(diào)函數(shù)接受resolve和reject方法作為參數(shù) 3.當(dāng)狀態(tài)改變后執(zhí)行then方法,并將resolve或reject的結(jié)果作為then方法接受回調(diào)函數(shù)的參數(shù)
class Mypromise{constructor(callback){this.status='pendding'//成功結(jié)果this.s_res = null// 失敗結(jié)果this.f_res = nullcallback((arg)=>{ // 使用箭頭函數(shù)this不會(huì)丟失// 改變狀態(tài)為成功this.status = 'fulfilled'this.s_res = arg},(arg)=>{// 改變狀態(tài)為失敗this.status = 'rejected'this.f_res = arg })}then(onresolve,onreject){if(this.status === 'fulfilled'){ // 當(dāng)狀態(tài)為成功時(shí)onresolve(this.s_res)}else if(this.status === 'rejected'){ // 當(dāng)狀態(tài)為失敗時(shí)onreject(this.f_res)}//在此我向大家推薦一個(gè)前端全棧開發(fā)交流圈:619586920 突破技術(shù)瓶頸,提升思維能力}
}
處理異步任務(wù)
原生調(diào)用方式
new Promise((resolve,reject)=>{setTimeOut(()=>{resolve(1)},1000)
}).then(res=>{console.log(res)
})
異步封裝思考 1.根據(jù)js執(zhí)行機(jī)制,setTimeOut屬于宏任務(wù),then回調(diào)函數(shù)屬于微任務(wù),當(dāng)主線程執(zhí)行完成后,會(huì)從異步隊(duì)列中取出本次的微任務(wù)先執(zhí)行。 2.也就是說(shuō),then方法執(zhí)行時(shí),狀態(tài)還沒(méi)有改變,所有我們需要將then方法執(zhí)行的回調(diào)保存起來(lái),等到異步代碼執(zhí)行完成后,在統(tǒng)一執(zhí)行then方法的回調(diào)函數(shù)
class Mypromise{constructor(callback){this.status='pendding'//成功結(jié)果this.s_res = null// 失敗結(jié)果this.f_res = nullthis.query = [] // ++ callback((arg)=>{ // 使用箭頭函數(shù)this不會(huì)丟失// 改變狀態(tài)為成功this.status = 'fulfilled'this.s_res = arg// 當(dāng)狀態(tài)改變后,統(tǒng)一執(zhí)行then方法的回調(diào)this.query.forEach(item=>{item.resolve(arg)})//在此我向大家推薦一個(gè)前端全棧開發(fā)交流圈:619586920 突破技術(shù)瓶頸,提升思維能力},(arg)=>{// 改變狀態(tài)為失敗this.status = 'rejected'this.f_res = arg // 當(dāng)狀態(tài)改變后,統(tǒng)一執(zhí)行then方法的回調(diào)this.query.forEach(item=>{item.reject(arg)})})}then(onresolve,onreject){if(this.status === 'fulfilled'){ // 當(dāng)狀態(tài)為成功時(shí)onresolve(this.s_res)}else if(this.status === 'rejected'){ // 當(dāng)狀態(tài)為失敗時(shí)onreject(this.f_res)}else{ // ++ 狀態(tài)沒(méi)有改變this.query.push({ // 保存回調(diào)函數(shù)到隊(duì)列中resolve:onresolve,reject:onreject})//在此我向大家推薦一個(gè)前端全棧開發(fā)交流圈:619586920 突破技術(shù)瓶頸,提升思維能力}}
}
處理鏈?zhǔn)秸{(diào)用
原生調(diào)用方式
new Promise((resolve,reject)=>{resolve(1)
}).then(res=>{return res
}).then(res=>{console.log(res)
})//在此我向大家推薦一個(gè)前端全棧開發(fā)交流圈:619586920 突破技術(shù)瓶頸,提升思維能力
鏈?zhǔn)秸{(diào)用思考
原生的Promise對(duì)象的then方法,返回的也是一個(gè)Promise對(duì)象,一個(gè)新的Promise才能支持鏈?zhǔn)秸{(diào)用 下一個(gè)then方法可以接受上一個(gè)then方法的返回值作為回調(diào)函數(shù)的參數(shù) 主要考慮上一個(gè)then方法的返回值: 1.Promise對(duì)象/具有then方法的對(duì)象 2.其他值 第一個(gè)then方法返回一個(gè)Promise對(duì)象,它的回調(diào)函數(shù)接受resFn和rejFN兩個(gè)回調(diào)函數(shù)作為參數(shù),把成功狀態(tài)的處理封裝為handle函數(shù),接受成功的結(jié)果作為參數(shù) 在handle函數(shù),根據(jù)onresolve返回值的不同做出不同的處理
class Mypromise{constructor(callback){this.status='pendding'//成功結(jié)果this.s_res = null// 失敗結(jié)果this.f_res = nullthis.query = [] // ++ callback((arg)=>{ // 使用箭頭函數(shù)this不會(huì)丟失// 改變狀態(tài)為成功this.status = 'fulfilled'this.s_res = arg// 當(dāng)狀態(tài)改變后,統(tǒng)一執(zhí)行then方法的回調(diào)this.query.forEach(item=>{item.resolve(arg)})},(arg)=>{// 改變狀態(tài)為失敗this.status = 'rejected'this.f_res = arg // 當(dāng)狀態(tài)改變后,統(tǒng)一執(zhí)行then方法的回調(diào)this.query.forEach(item=>{item.reject(arg)})})}then(onresolve,onreject){return new Mypromise((resFN,rejFN)=>{if(this.status === 'fulfilled'){ // 當(dāng)狀態(tài)為成功時(shí)handle(this.s_res)}else if(this.status === 'rejected'){ // 當(dāng)狀態(tài)為失敗時(shí)errBack(this.f_res)}else{ // ++ 狀態(tài)沒(méi)有改變this.query.push({ // 保存回調(diào)函數(shù)到隊(duì)列中resolve:onresolve,reject:onreject})} //在此我向大家推薦一個(gè)前端全棧開發(fā)交流圈:619586920 突破技術(shù)瓶頸,提升思維能力function handle(value){// 當(dāng)then方法的onresolve方法有返回值時(shí),保存其返回值,沒(méi)有使用其保存的值let returnVal = onresolve instanceof Function && onresolve(value) || value// 如果onresolve方法返回的是promise對(duì)象,則調(diào)用其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方法
原生調(diào)用方式 Promise.all方法接受一個(gè)數(shù)組,數(shù)組中的每一項(xiàng)都是一個(gè)Promise實(shí)例,只有數(shù)組中的所有Promise實(shí)例的狀態(tài)都變?yōu)閒ulfilled時(shí),此時(shí)整個(gè)狀態(tài)才會(huì)變成fulfilled,此時(shí)數(shù)組中所有Promise實(shí)例的返回值組成一個(gè)新的數(shù)組,進(jìn)行傳遞。 Promise.race方法和Promise.all方法一樣,如果不是Promise實(shí)例,就會(huì)先調(diào)用Promise.resolve方法,將參數(shù)轉(zhuǎn)為Promise實(shí)例,在進(jìn)行下一步處理。 只要數(shù)組中有一個(gè)參數(shù)的狀態(tài)變?yōu)閒ulfilled就會(huì)進(jìn)行傳遞
// 將現(xiàn)有對(duì)象轉(zhuǎn)換為Promise對(duì)象Mypromise.resolve = (arg)=>{if(typeof arg == 'undefined' || arg==null){ // 不帶有任何參數(shù)return new Mypromise(resolve=>{resolve(arg)})}else if(arg instanceof Mypromise){ // 是一個(gè)Mypromise實(shí)例return arg}else if(arg['then'] instanceof Function){ // 具有then方法的對(duì)象return new Mypromise((resolve,reject)=>{arg.then(res=>{resolve(res)},err=>{reject(err)})//在此我向大家推薦一個(gè)前端全棧開發(fā)交流圈:619586920 突破技術(shù)瓶頸,提升思維能力})}else{ // 參數(shù)不是具有then方法的對(duì)象,或根本不是對(duì)象return new Mypromise(resolve=>{resolve(arg)}) }}Mypromise.all = (arr)=>{if(!Array.isArray(arr)){throw new TypeError('參數(shù)必須是一個(gè)數(shù)組')}return new Mypromise((resolve,reject)=>{let i=0,result=[]next()functon next(){// 如果不是Mypromise實(shí)例需要轉(zhuǎn)換Mypromise.resolve(arr[i]).then(res=>{result.push(res)i++if(i===arr.length){resolve(result)}else{next()}},reject)}})}//在此我向大家推薦一個(gè)前端全棧開發(fā)交流圈:619586920 突破技術(shù)瓶頸,提升思維能力Mypromise.race = (arr)=>{if(!Array.isArray(arr)){throw new TypeError('參數(shù)必須是一個(gè)數(shù)組')}return new Mypromise((resolve,reject)=>{let done = falsearr.forEach(item=>{Mypromise.resolve(item).then(res=>{if(!done){resolve(res)done = true}},err=>{if(!done){reject(res)done = true}})})})} 處理Mypromise狀態(tài)確定不能改變的特性
在重寫callback中的resolve和reject方法執(zhí)行前,先判斷狀態(tài)是否為'pendding'
結(jié)語(yǔ)
感謝您的觀看,如有不足之處,歡迎批評(píng)指正。
總結(jié)
以上是生活随笔 為你收集整理的深度解析利用ES6进行Promise封装总结 的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔 網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔 推薦給好友。