[英]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.