如何用RxJS控制多个ajax调用的压力

时间:2018-01-22 08:02:31

标签: javascript node.js rxjs rxjs5 rxjs-dom

使用RxJS 5我想解决以下问题:

让我们说我从REST API中获取了各种类别的列表。

基于每个类别和其中一个类别,我想从另一个REST端点获取子类别。

然后,根据每个子类别和其中一个子类别,我想获取产品,我们需要获取每个产品和其中一个产品以获取详细说明。

我已经解决了。问题是ajax调用会升级,只需一分钟就可以进行超过30k的调用,这会导致服务器瘫痪。

现在,因为这是一个夜间工作,我可以花一些时间,只要它成功完成。

这就是我所拥有的:

getCategories() // Wraps ajax call and returns payload with array of categories
      .switchMap(categories => Observable.from(categories))
      .mergeMap(category => 
        getSubCategories(category) // Wraps ajax call and returns payload with array of sub categories
          .catch(err => {
            console.error('Error when fetching sub categories for category:', category);
            console.error(err);
            return Observable.empty();
          })
      )
      .mergeMap(subCategories => Observable.from(subCategories))
      .mergeMap(subCategory => 
        getProducts(subCategory) // Wraps ajax call and returns payload with array of products
        .catch(err => {
          console.error('Error when fetching products for sub category:', subCategory);
          console.error(err);
          return Observable.empty();
        })
      )
      .mergeMap(products => Observable.from(products))
      .mergeMap(product => 
        getProductDetails(product) // Wraps ajax call and returns payload with product details
        .catch(err => {
          console.error('Error when fetching product details for product:', product);
          console.error(err);
          return Observable.empty();
        })
      )
      .mergeMap(productDetails => saveToDb(productDetails))
      .catch(err => {
        console.error(err);
      })
      .subscribe();

在我获取类别的初始请求之后,我想:

每次调用获取子类别的调用应该等到前一个调用完成。在获取产品和产品详细信息时,一次只能进行5次ajax调用。完成这5次通话后,我们会触发接下来的5次通话等。

或者可以在我们进行下一次ajax调用之前等待x秒等时间控制它。

如何基于上面的例子使用RxJS来解决这个问题呢?

1 个答案:

答案 0 :(得分:3)

mergeMap有一个带有可选并发参数的重载。您可以使用它来控制同时向服务器发送的请求数。

  

public mergeMap(project: function(value: T, ?index: number): ObservableInput, resultSelector: function(outerValue: T, innerValue: I, outerIndex: number, innerIndex: number): any, concurrent: number): Observable

  .mergeMap(category => 
    getSubCategories(category) // Wraps ajax call and returns payload with array of sub categories
      .catch(err => {
        console.error('Error when fetching sub categories for category:', category);
        console.error(err);
        return Observable.empty();
      }),
    null, 
    5 /* concurrency */
  )

也; mergeMap会将observableLike转换为Observables,因此如果getSubCategories()返回一个自动转换为observable的Array,则不需要Observable.from()