[英]Limit number of requests at a time with RxJS
假設我有 10 個 url,我希望為每個 url 發出一個 HTTP 請求。
我可以創建一個 URL 的可觀察對象,然后.flatMap()
為每個 URL 的請求,然后.subscribe
獲取結果。 但這會同時發出所有請求。
有沒有辦法將請求數量限制為固定數量,以免服務器超載
通過 mergeMap 管道,將並行限制作為第二個參數
const MAX_PARALLEL_QUERIES = 3;
let allResults = [];
let observables = [] // fill with observables
from(observables)
.pipe(mergeMap(observable => observable, MAX_PARALLEL_QUERIES))
.subscribe(
partialResults => {
allResults = allResults.concat(partialResults);
},
err => {
// handle error
},
() => {
// get here when all obserable has returned
allResults.forEach(result=> {
// do what you want
});
}
);
現在是 2018 年,rxjs 5 來了,這就是我解決它的方法
urls$
.mergeMap((url) => request({ url }), null, 10)
.subscribe()
mergeMap
(又名flatMap
)已經將“最大並發性”作為其第三個參數(請參閱文檔)
順便提一句。 我正在使用 universal-rxjs-ajax( request
)來實現節點兼容性,但它應該與Observable.ajax
一樣工作
這個問題在這里有答案: how-to-limit-the-concurrency-of-flatmap您也可以在此處查看答案並行觸發異步請求但使用 rxjs 按順序獲取結果
基本上它圍繞着使用merge(withMaxConcurrency)
運算符。
我遇到了同樣的問題,現在找到了解決方案。 參考這個答案
如果你通過 fromNodeCallback 或 return Promise 創建 observable,它會創建一個熱 observable,並會在 flatMap 和訂閱后立即執行。 所以 flatMapWithMaxConcurrent 或 map&merge 沒有按預期工作。
var start = Date.now() var now = ()=>Date.now()-start var test = Rx.Observable.fromNodeCallback(function(i, cb){ console.log(i, 'access', now()); setTimeout(function(){ cb(null, i) }, 1000); }) Rx.Observable.from([1,2,3]).flatMapWithMaxConcurrent(1, x=>test(x) ).subscribe(x=>console.log(x, 'finish', now())) /* output: 1 access 2 2 access 16 3 access 16 1 finish 1016 2 finish 1016 3 finish 1017 */
<script src="http://www.cdnjs.net/ajax/libs/rxjs/4.1.0/rx.all.js"></script>
您需要將其轉換為冷可觀察對象,只需使用 Rx.Observable.defer。
var start = Date.now() var now = ()=>Date.now()-start var test = Rx.Observable.fromNodeCallback(function(i, cb){ console.log(i, 'access', now()); setTimeout(function(){ cb(null, i) }, 1000); }) Rx.Observable.from([1,2,3]).flatMapWithMaxConcurrent(1, x=>Rx.Observable.defer( ()=>test(x)) ) //.map(x=>Rx.Observable.defer( ()=>test(x)) ).merge(1) // this works too.subscribe(x=>console.log(x, 'finish', now())) /* output: 1 access 3 1 finish 1004 2 access 1005 2 finish 2005 3 access 2006 3 finish 3006 */
<script src="http://www.cdnjs.net/ajax/libs/rxjs/4.1.0/rx.all.js"></script>
這里只是一個旁注:在 RxJS v5 中, fromCallback()
和fromNodeCallback()
分別更改為bindCallback()
和bindNodeCallback()
。 進一步閱讀鏈接: bindNodeCallback
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.