简体   繁体   English

使用 RxJS 一次限制请求数

[英]Limit number of requests at a time with RxJS

Suppose I have 10 urls, and I wish to make an HTTP request for each one of them.假设我有 10 个 url,我希望为每个 url 发出一个 HTTP 请求。

I could create an observable of the URLs, then .flatMap() the requests for each one of them, and then .subscribe for the results.我可以创建一个 URL 的可观察对象,然后.flatMap()为每个 URL 的请求,然后.subscribe获取结果。 But that would make all of the requests at once.但这会同时发出所有请求。

Is there a way to impose a limit to the number of requests to a fixed number, in order not to overload the server有没有办法将请求数量限制为固定数量,以免服务器超载

RxJS v6 update RxJS v6 更新

pipe through mergeMap with your parallel limit as 2nd parameter通过 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
                    });
                }
            );

It's 2018, rxjs 5 is here and this is how I solved it现在是 2018 年,rxjs 5 来了,这就是我解决它的方法

urls$
  .mergeMap((url) => request({ url }), null, 10)
  .subscribe()

mergeMap (aka flatMap ) already takes the "max concurrency" as its 3rd parameter (see thedocs ) mergeMap (又名flatMap )已经将“最大并发性”作为其第三个参数(请参阅文档

Btw.顺便提一句。 I am using universal-rxjs-ajax (the request ) for node compatibility, but it should work the same with Observable.ajax我正在使用 universal-rxjs-ajax( request )来实现节点兼容性,但它应该与Observable.ajax一样工作

This question has an answer here: how-to-limit-the-concurrency-of-flatmap You can also review the answer here Fire async request in parallel but get result in order using rxjs这个问题在这里有答案: how-to-limit-the-concurrency-of-flatmap您也可以在此处查看答案并行触发异步请求但使用 rxjs 按顺序获取结果

Basically it revolves around using the merge(withMaxConcurrency) operator.基本上它围绕着使用merge(withMaxConcurrency)运算符。

I got the same problem, and now found the solution.我遇到了同样的问题,现在找到了解决方案。 reference to this answer参考这个答案

If you create observable by fromNodeCallback or return Promise, it create a hot observable, and will execute immediately once flatMap and subscribe.如果你通过 fromNodeCallback 或 return Promise 创建 observable,它会创建一个热 observable,并会在 flatMap 和订阅后立即执行。 So flatMapWithMaxConcurrent or map&merge not work as expected.所以 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>

You need convert it to cold observable, simply use Rx.Observable.defer.您需要将其转换为冷可观察对象,只需使用 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>

Just a side note here: in RxJS v5 fromCallback() and fromNodeCallback() were changed to bindCallback() and bindNodeCallback() respectively.这里只是一个旁注:在 RxJS v5 中, fromCallback()fromNodeCallback()分别更改为bindCallback()bindNodeCallback() Link for further reading: bindNodeCallback进一步阅读链接: bindNodeCallback

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM