摘要:原文地址本篇文章主要是想通過中提供的幾個(gè)方法,來實(shí)現(xiàn)諸如等各種變體方法在標(biāo)準(zhǔn)的規(guī)范中,提供了和兩種,我們首先來了解下這兩個(gè)方法是干嘛的,方便我們后面工作的展開。表示只獲取所有的中進(jìn)入完成狀態(tài)的結(jié)果,被拒絕的則忽略掉。
原文地址: https://www.xiabingbao.com/po...
本篇文章主要是想通過ES6中Promise提供的幾個(gè)方法,來實(shí)現(xiàn)諸如first、last、none、any等各種變體方法!
在標(biāo)準(zhǔn)的ES6規(guī)范中,提供了Promise.all和Promise.race兩種,我們首先來了解下這兩個(gè)方法是干嘛的,方便我們后面工作的展開。Promise.all中所有的Promise實(shí)例都處于完成狀態(tài),該方法才進(jìn)入完成狀態(tài),否則任意一個(gè)被拒絕,則該方法進(jìn)入拒絕狀態(tài),并舍棄其他所有完成的結(jié)果,拒絕原因是第一個(gè)被拒絕的實(shí)例的原因。Promise.race中任意的一個(gè)Promise實(shí)例變成完成狀態(tài)或者拒絕狀態(tài),則race結(jié)束,race的結(jié)果即為第一個(gè)變成最終狀態(tài)的結(jié)果!更詳細(xì)的可以參考下阮一峰的文章Promise對象之Promise.all。
1. 準(zhǔn)備工作在開始編寫各種變體方法之前,這里我們首先定義幾個(gè)一會(huì)兒要使用的幾個(gè)Promise實(shí)例:
/** * 創(chuàng)建一個(gè)Promise對象的實(shí)例 * @param name {string} 該實(shí)例的名稱 * @param flag {boolean} 返回的結(jié)果狀態(tài):完成還是拒絕 * @param diff {number} 延遲的時(shí)間 */ var createPromiseCase = ( name, flag, diff ) => { return new Promise( ( resolve, reject ) => { setTimeout( () => { flag ? resolve( name ) : reject( new Error( "testPromise is error, name: " + name ) ); }, diff ); } ); }; var p1_suc_100 = createPromiseCase( "p1-suc-100", true, 100 ); var p2_suc_500 = createPromiseCase( "p2-suc-500", true, 500 ); var p3_suc_300 = createPromiseCase( "p3-suc-300", true, 300 ); var p4_fail_400 = createPromiseCase( "p4-fail-400", false, 400 ); var p5_fail_200 = createPromiseCase( "p5-fail-200", false, 200 );2. 各種變體方法 2.1 Promise.first
場景:一個(gè)頁面當(dāng)前正處于loading狀態(tài),同時(shí)請求了多個(gè)接口,無論哪個(gè)接口正確返回結(jié)果,則loading效果取消!或者其他的要獲取獲取第一個(gè)完成狀態(tài)的值。
這里就要用到了Promise.first了,只要任意一個(gè)Promise實(shí)例變成完成狀態(tài),則Promise.first變成完成狀態(tài)。其實(shí)這里并不適合Promise.race方法,因?yàn)榈谝粋€(gè)變成拒絕狀態(tài)的實(shí)例也會(huì)激活Promise.race,
if ( !Promise.first ) { // get first resolve result Promise.first = promiseList => { return new Promise( ( resolve, reject ) => { var num = 0; var len = promiseList.length; promiseList.forEach( pms => { Promise.resolve( pms ).then( resolve ).catch( () => { num++; if ( num === len ) { reject( "all promises not resolve" ); } } ); } ); } ); }; }
調(diào)用方式:
Promise.first([p4_fail_400, p2_suc_500, p3_suc_300]) .then(res => console.log(res)) // p3-suc-300 .catch(e => console.error(e))
可以看到每次獲取的p3_suc_300的值,因?yàn)閜4是失敗的狀態(tài),p2的完成狀態(tài)沒有p3快,因此這里獲取到了p3的結(jié)果。
2.2 Promise.last與Promise.first對應(yīng)的則是Promise.last,獲取最后變成完成狀態(tài)的值。這里與Promise.first不同的是,只有最后一個(gè)Promise都變成最終態(tài)(完成或拒絕),才能知道哪個(gè)是最后一個(gè)完成的,這里我采用了計(jì)數(shù)的方式,then和catch只能二選一,等計(jì)數(shù)器達(dá)到list.length時(shí),執(zhí)行外部的resolve。
if ( !Promise.last ) { // get last resolve result Promise.last = promiseList => { return new Promise( (resolve, reject) => { let num = 0; let len = promiseList.length; let lastResolvedResult; const fn = () => { if (++num===len) { lastResolvedResult ? resolve(lastResolvedResult) : reject("all promises rejected"); } } promiseList.forEach( pms => { Promise.resolve( pms ) .then(res => { lastResolvedResult = res; fn() }) .catch(fn); } ) } ) } }
調(diào)用方式:
Promise.last([p1_suc_100, p2_suc_500, p5_fail_200, p3_suc_300, p4_fail_400]) .then(res => console.log(res)) // p2-suc-500 .catch(e => console.error(e))
p2需要500ms才能完成,是最晚完成的。
2.3 Promise.nonePromise.none與Promise.all正好相反,所有的promise都被拒絕了,則Promise.none變成完成狀態(tài)。該方法可以用Promise.first來切換,當(dāng)執(zhí)行Promise.first的catch時(shí),則執(zhí)行Promise.none中的resolve。不過這里我們使用Promise.all來實(shí)現(xiàn)。
if ( !Promise.none ) { // if all the promises rejected, then succes Promise.none = promiseList => { return Promise.all( promiseList.map( pms => { return new Promise( ( resolve, reject ) => { // 將pms的resolve和reject反過來 return Promise.resolve( pms ).then( reject, resolve ); } ) } ) ) } }
調(diào)用方式:
Promise.none([p5_fail_200, p4_fail_400]) .then(res => console.log(res)) .catch(e => console.error(e)) // then的輸出結(jié)果: // [ // Error: testPromise is error, name: p5-fail-200, // Error: testPromise is error, name: p4-fail-400 // ]
兩個(gè)promise都失敗后,則Promise.none進(jìn)入完成狀態(tài)。
2.4 Promise.anyPromise.any表示只獲取所有的promise中進(jìn)入完成狀態(tài)的結(jié)果,被拒絕的則忽略掉。
if ( !Promise.any ) { // get only resolve the results Promise.any = promiseList => { let result = []; return Promise.all( promiseList.map( pms => { return Promise.resolve( pms ) .then( res => result.push( res ) ) .catch( e => { } ); } ) ).then( ( res ) => { return new Promise( ( resolve, reject ) => { result.length ? resolve( result ) : reject(); } ) } ) } }
調(diào)用方式:
Promise.any([p1_suc_100, p2_suc_500, p5_fail_200, p3_suc_300, p4_fail_400]) .then(res => console.log(res)) // ["p1-suc-100", "p3-suc-300", "p2-suc-500"] .catch(e => console.error(e))2.5 Promise.every
最后一個(gè)的實(shí)現(xiàn)比較簡單,所有的promise都進(jìn)入完成狀態(tài),則返回true,否則返回false。
if (!Promise.every) { // get the boolean if all promises resolved Promise.every = promiseList => { return Promise.all(promiseList) .then(() => Promise.resolve(true)) .catch(() => Promise.resolve(false)); } }
調(diào)用方式:
Promise.every([p1_suc_100, p2_suc_500, p3_suc_300]) .then(result => console.log("Promise.every", result)); // Promise.every true Promise.every([p1_suc_100, p4_fail_400]) .then(result => console.log("Promise.every", result)); // Promise.every false3. 總結(jié)
Promise還有各種方面的應(yīng)用,很多類庫也都實(shí)現(xiàn)了類似的方法,這里也僅僅是鄙人拙見,稍微實(shí)現(xiàn)了Promise的變體方法,加深下對Promise的理解。
原文地址: 蚊子的博客
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/103402.html
摘要:所以僅用于簡化理解,快速入門,依然需要閱讀有深入研究的文章來加深對各種異步流程控制的方法的掌握。 原文地址:http://zodiacg.net/2015/08/javascript-async-control-flow/ 隨著ES6標(biāo)準(zhǔn)逐漸成熟,利用Promise和Generator解決回調(diào)地獄問題的話題一直很熱門。但是對解決流程控制/回調(diào)地獄問題的各種工具認(rèn)識(shí)仍然比較麻煩。最近兩天...
摘要:前言對于這門語言,其實(shí)我更喜歡稱它為,從一開始我們就已經(jīng)涉及到異步編程,但是多數(shù)開發(fā)者從來沒有認(rèn)真思考過自己程序中的異步,到底是怎么實(shí)現(xiàn)的,以及為什么會(huì)出現(xiàn)。 前言 對于JavaScript這門語言,其實(shí)我更喜歡稱它為ECMAScript,從一開始我們就已經(jīng)涉及到異步編程,但是多數(shù)JavaScript開發(fā)者從來沒有認(rèn)真思考過自己程序中的異步,到底是怎么實(shí)現(xiàn)的,以及為什么會(huì)出現(xiàn)。但是由于...
摘要:寫在前面這一章的順序?qū)τ谖唇佑|過使用過的童鞋而言略抽象了,前邊幾章主要為了說明和之前的異步方式相比有什么優(yōu)勢和它能解決什么問題,后邊才詳解的設(shè)計(jì)和各種場景下如何使用。建議先了解和簡單使用過后再閱讀,效果更佳。 寫在前面:Promise這一章的順序?qū)τ谖唇佑|過使用過Promise的童鞋而言略抽象了,前邊幾章主要為了說明Promise和之前的異步方式相比有什么優(yōu)勢和它能解決什么問題,后邊才...
摘要:本文最早為雙十一而作,原標(biāo)題雙大前端工程師讀書清單,以付費(fèi)的形式發(fā)布在上。發(fā)布完本次預(yù)告后,捕捉到了一個(gè)友善的吐槽讀書清單也要收費(fèi)。這本書便從的異步編程講起,幫助我們設(shè)計(jì)快速響應(yīng)的網(wǎng)絡(luò)應(yīng)用,而非簡單的頁面。 本文最早為雙十一而作,原標(biāo)題雙 11 大前端工程師讀書清單,以付費(fèi)的形式發(fā)布在 GitChat 上。發(fā)布之后在讀者圈群聊中和讀者進(jìn)行了深入的交流,現(xiàn)免費(fèi)分享到這里,不足之處歡迎指教...
摘要:本文最早為雙十一而作,原標(biāo)題雙大前端工程師讀書清單,以付費(fèi)的形式發(fā)布在上。發(fā)布完本次預(yù)告后,捕捉到了一個(gè)友善的吐槽讀書清單也要收費(fèi)。這本書便從的異步編程講起,幫助我們設(shè)計(jì)快速響應(yīng)的網(wǎng)絡(luò)應(yīng)用,而非簡單的頁面。 本文最早為雙十一而作,原標(biāo)題雙 11 大前端工程師讀書清單,以付費(fèi)的形式發(fā)布在 GitChat 上。發(fā)布之后在讀者圈群聊中和讀者進(jìn)行了深入的交流,現(xiàn)免費(fèi)分享到這里,不足之處歡迎指教...
閱讀 4392·2021-11-24 10:24
閱讀 1419·2021-11-22 15:22
閱讀 2048·2021-11-17 09:33
閱讀 2457·2021-09-22 15:29
閱讀 526·2019-08-30 15:55
閱讀 1666·2019-08-29 18:42
閱讀 2742·2019-08-29 12:55
閱讀 1784·2019-08-26 13:55