假设我有10个网址,我希望为每个网址发出HTTP请求。
我可以创建一个可观察的网址,然后.flatMap()
创建每个网址的请求,然后.subscribe
查看结果。但这会立即产生所有要求。
是否有办法对固定号码的请求数施加限制,以免服务器超载
答案 0 :(得分:6)
2018年,rxjs 5就在这里,这就是我解决它的方式
urls$
.mergeMap((url) => request({ url }), null, 10)
.subscribe()
mergeMap
(又名flatMap
)已经采用" max并发"作为其第三个参数(参见docs)
顺便说一下。我使用universal-rxjs-ajax(request
)来实现节点兼容性,但它应该与Observable.ajax
答案 1 :(得分:3)
这个问题的答案如下:how-to-limit-the-concurrency-of-flatmap 您还可以在此处查看答案Fire async request in parallel but get result in order using rxjs
基本上它围绕着使用merge(withMaxConcurrency)
运算符。
答案 2 :(得分:2)
对于rxjs v6: 通过并行映射将您的并行限制作为第二个参数
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
});
}
);
答案 3 :(得分:1)
我遇到了同样的问题,现在找到了解决方案。 参考this answer
如果你通过fromNodeCallback创建observable或者返回Promise,它会创建一个hot observable,并且会在flatMap和subscribe之后立即执行。所以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>
&#13;
您需要将其转换为冷可观察,只需使用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
*/
&#13;
<script src="http://www.cdnjs.net/ajax/libs/rxjs/4.1.0/rx.all.js"></script>
&#13;
答案 4 :(得分:0)
这里只是旁注:在RxJS v5中fromCallback()
和fromNodeCallback()
分别更改为bindCallback()
和bindNodeCallback()
。进一步阅读的链接:bindNodeCallback