Rxjs:基于条件的递归 Http 调用

Rxjs: Recursive Http calls based on condition

我使用以下命令通过给出固定数量的记录来检索列表。在下面的示例中,它 returns 100 条记录(我传递了 pageIndex 值并且应该在每个请求中增加它以获得下一个 100 条记录):

this.employeeService.list(1, 100).toPromise().then(data => {
    this.employees = data.items;
});

数据中有一个名为 isComplete 的标志,如果 data.isComplete 值为 false,我想对相同的列表方法进行相同的 Http 调用.在 Angular 中使用 Rxjs 执行此操作的正确方法是什么?有一些方法,例如递归订阅等,但似乎不适合这种情况。

expand 运算符就是您要找的。示例:

this.employeeService.list(100).pipe(
    expand((data) => {
        if(data.isComplete) {
            return of(EMPTY);
        } else {
            return this.employeeService.list(100);
        }
    })
).subscribe((data) => {
    //your logic here
});

可能的解决方案:

您可能想要展开和缩小:

我假设页面索引从 0 开始,您在 'expand' 之前开始的页面索引必须比您服务的第一页索引小 1。

of({
  isComplete: false,
  pageIndex: -1,
  items: []
}).pipe(
  expand(data => this.employeeService.list(data.pageIndex+1, 100).pipe(
    map(newData => ({...newData, pageIndex: data.pageIndex+1}))
  )),
  takeWhile(data => !(data.isComplete === true), true),
  map(data => data.items),
  reduce((acc, items) => ([...acc, ...items]))
).subscribe(res => {
  this.employees = res;
});

关于承诺的快速旁白:

observableStream.toPromise().then(LAMBDA);

大致相当于

observableStream.pipe(last()).subscribe(LAMBDA);

last 等待源竞争,只发出最终值。这会丢弃流中的所有其他值。

许多第一次使用 Observables 和 Promises 的人倾向于认为它更像:

observableStream.pipe(first()).subscribe(LAMBDA);

以便它获取第一个值,然后尽快用该值解析 Promise。其实不然。


一般来说,坚持使用其中一个是明智的。 Observable 是 Promises 的超集。缺少期望承诺的第三方库,永远不会需要将 Observable 转换为 Promise。