【问题标题】:How to control pressure of multiple ajax calls with RxJS如何使用 RxJS 控制多个 ajax 调用的压力
【发布时间】:2018-06-30 19:32:13
【问题描述】:

使用 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 很好地解决这个问题?

【问题讨论】:

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


    【解决方案1】:

    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 的数组,则不需要进一步的 Observable.from()

    【讨论】:

    • 非常感谢你的洞察力,我会在一段时间内尝试。我阅读了更多关于 mergeMap 的文档,我应该使用 resultSelector 而不是使用 .map 或 .pluck 选择响应数据吗?
    • @Spetastium 这取决于您的需求。 resultSelector 非常方便,如果您需要访问 mergeMap 的输入以将其与 project 函数发出的每个值结合起来(例如: get 用户文档,发出 元组 将受益于结果选择器)
    猜你喜欢
    • 2018-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-25
    • 1970-01-01
    • 1970-01-01
    • 2020-04-13
    • 1970-01-01
    相关资源
    最近更新 更多