重复查询直到满足条件

时间:2021-04-29 23:28:18

标签: angular rxjs observable takeuntil

我对返回 350 条记录的 API 发出 HTTP 请求。每个项目都有一个名为“total”的属性。我需要随机选择 5 个项目,而且这 5 个项目的“总”属性总和应该小于 30。我认为这可以使用 takeUntil 来完成,但我仍然没有知道如何构建代码以实现这一目标。

products$ = combineLatest([
    this._productService.robots$,
    this.refreshProductAction$
  ]).pipe(
    map(([products, action]) =>
      products.sort(() => (Math.random() - Math.random())).slice(0, 5),
    )
  );

这是“扩展”运算符的一个示例,但我不知道如何跟踪总和并在高于 50 的情况下再次重新执行可观察对象。

1 个答案:

答案 0 :(得分:1)

如果我理解正确,您会收到 350 个“产品”,并且只调用一次 API,如果 5 个随机选择的“产品”的“总和”大于 50,则需要重复此操作。

因此,如果这种理解是正确的,我将继续使用 expand 运算符递归调用 API,直到满足所需条件,然后使用 last 运算符仅通知发出的最后一个值,这是第一个满足条件的。下面的例子试图用内联注释解释逻辑。

products$ = combineLatest([
  this._productService.robots$,
  this.refreshProductAction$
]).pipe(
  // use expand operator to recursively repeat the API call if the sum is higher than 50, 
  // otherwise return the empty Observable, which means simply to complete the stream
  expand(([products, action]) => {
    const fiveProducts = products.sort(() => (Math.random() - Math.random())).slice(0, 5);
    // use the "reduce" method of Array to calculate the sum
    const sumOfFiveTotals = fiveProducts.reduce((s, p) => s = s + p.total, 0);
    return sumOfFiveTotals > 50 ? 
       // I assume this._productService.robots$, when subscribed, calls the API
       // you can pipe a "delay" operator after this._productService.robots$ if you want to add some delay between subsequent API calls
       this._productService.robots$ :
       EMPTY  // the empty Observable
  }),
  // notifies only the last value emitted by the upstream
  last()
);