摘要:調用分布式服務接口時經常會遇到這樣的問題接口方提供多個供用戶調用,只要有一個返回成功就算成功。但是請注意不是等到有一個被時返回,而是只要有一個被時就會返回,不論這個是還是。
調用分布式服務接口時經常會遇到這樣的問題:接口方提供多個 IP 供用戶調用,只要有一個返回成功就算成功。
對于這樣的問題,一個比較簡單的方案是依次調用各個接口,如果前一個接口未成功返回再調用第二個接口。這樣做的好處是對于服務器資源消耗比較小,但對于用戶來說效率非常低下。設想調用第一個接口經過 20 秒超時出錯才調用第二個接口,如果第二個接口又是 20 秒超時,用戶就已經等待了 40 秒。用戶的等待時間按線性增長,這樣的結果時不可接受的。
好的解決方案是同時并發調用所有接口,有些同學可能會想到 Promise.race。但是請注意:Promise.race 不是等到有一個 Promise 被 resolve 時返回,而是只要有一個 Promise 被 fulfill 時就會返回,不論這個 Promise 是 resolve 還是 reject。
我就遇到過類似問題,當然也被 Promise.race 坑害了一回。上谷歌搜到了老外這篇博文:Promise me you won’t use Promise.race。博文中詳細探討了這個問題,并用 Promise.race 實現了一個解決方案:
Promise.properRace = function properRace(promises) { if (promises.length < 1) { return Promise.reject("Can"t start a race without promises!"); } // There is no way to know which promise is rejected. // So we map it to a new promise to return the index when it fails const indexPromises = promises.map((p, index) => p.catch(e => { console.debug("Promise rejected in `properRace`: " + e); return Promise.reject(index); })); return Promise.race(indexPromises).catch(index => { // The promise has rejected, remove it from the list of promises and just continue the race. promises.splice(index, 1)[0].catch(() => { /* eat this */ }); return promises.length ? properRace(promises) : Promise.reject("All promises rejected"); }); };
雖然略顯復雜,但方法確實很巧妙,我初期就使用了這種方法。最近回過頭來突然想到:properRace 的需求是只要有一個被 resolve 返回的 Promise 就被 resolve;JavaScript 雖然沒有提供這樣的函數,但是提供了另外一個很相似的函數:只要有一個被 reject 返回的 Promise 就被 reject。
這個函數我們很常用,就是:Promise.all
想到這一層,那么用它來實現 properRace 就很簡單了:把傳入的 Promise 數組狀態正反對調就好了。結果如下:
Promise.properRace = function properRace(promises) { const resolve = Promise.resolve.bind(Promise); const reject = Promise.reject.bind(Promise); return Promise.all(promises.map(x => x.then(reject, resolve))) .then(reject, resolve); }
完
2019年7月更新此方法已經被標準化為 Promise.any
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/107218.html
摘要:我們使用關鍵字和提供的和回調函數來創建新的根據異步任務的返回結果,開發者可以在回調函數體的內部手動調用或者。第一個方法的回調函數接收方法里的值當被時,會調用回調方法。如果被,而方法在之后,那回調函數永遠不會被執行。 盡管同步代碼易于追蹤和調試,但異步代碼普遍在性能和靈活性上更具優勢。Why hold up the show when you can trigger numerous r...
摘要:通過或者拿到方法回調函數的返回值,然后調用,將新增的的和傳入到中。打印結果實現方法接收一個包含多個的數組,當有一個為狀態時,整個大的為,并執行回調函數。 前言 Promise大家一定都不陌生了,JavaScript異步流程從最初的Callback,到Promise,到Generator,再到目前使用最多的Async/Await(如果對于這些不熟悉的可以參考我另一篇文章《JavaScri...
摘要:本文從入手,系統的回顧的異步機制及發展歷程。需要提醒的是,文本沒有討論的異步機制。這就是之前提到的事件觸發線程。其實無論是請求還是定時器還是事件,我們都可以統稱它們為事件。第二階段,引擎線程專注于處理事件。將外元素的事件回調放入調用棧。 functionshowImg(url){ varframeid=frameimg+Math.random(); window.img=window....
摘要:解決異步編程有兩種主要方式事件模型和回調函數。將異步操作以同步操作的流程表達出來,避免了層層嵌套回調函數。方法是的別名,相當于函數的第一個參數傳入,第二個參數傳入發生錯誤時的回調函數。 JavaScript 解決異步編程有兩種主要方式:事件模型和回調函數。但是隨著業務越來越復雜,這兩種方式已經不能滿足開發者的需求了,Promise 可以解決這方面的問題。為了更好的理解 Promise ...
摘要:方法是的別名,用于指定發生錯誤時的回調函數。由于字符串不屬于異步操作判斷方法是字符串對象不具有方法,返回實例的狀態從一生成就是,所以回調函數會立即執行。出錯了等同于出錯了出錯了上面的代碼生成一個對象的實例,狀態為,回調函數會立即執行。 引言 Promise 是異步編程的一種解決方案,比傳統的解決方案——回調和事件——更合理且強大。最近的項目要用到這個,就參照阮一峰老師的《ES6標準入門...
閱讀 2951·2021-11-25 09:43
閱讀 3327·2021-11-24 09:39
閱讀 2828·2021-09-22 15:59
閱讀 2174·2021-09-13 10:24
閱讀 509·2019-08-29 17:02
閱讀 2098·2019-08-29 13:23
閱讀 3058·2019-08-29 13:06
閱讀 3539·2019-08-29 13:04