使用RxJS限制一次请求数

时间:2015-12-30 19:12:06

标签: javascript rxjs

假设我有10个网址,我希望为每个网址发出HTTP请求。

我可以创建一个可观察的网址,然后.flatMap()创建每个网址的请求,然后.subscribe查看结果。但这会立即产生所有要求。

是否有办法对固定号码的请求数施加限制,以免服务器超载

5 个答案:

答案 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;
&#13;
&#13;

您需要将其转换为冷可观察,只需使用Rx.Observable.defer。

&#13;
&#13;
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;
&#13;
&#13;

答案 4 :(得分:0)

这里只是旁注:在RxJS v5中fromCallback()fromNodeCallback()分别更改为bindCallback()bindNodeCallback()。进一步阅读的链接:bindNodeCallback