【问题标题】:Rxjs: Recursive Http calls based on condition [closed]Rxjs:基于条件的递归 Http 调用 [关闭]
【发布时间】:2021-05-03 13:54:10
【问题描述】:

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

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

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

【问题讨论】:

    标签: javascript angular typescript rxjs observable


    【解决方案1】:

    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
    });
    

    【讨论】:

    • 非常感谢,我会尽力通知您结果。我应该使用toPromise()subscribe 来填充下拉列表(对于本示例和其他情况,一次填充所有下拉列表)?
    • 顺便说一句,现在当然投赞成票;)
    • @Jonathan Observables 比 Promise 强大得多。根据您的用例,只需使用您喜欢的那个。对我来说,这是可观察的 :-)
    • 您的解决方案简单易用。但是,我认为我们需要进行一些修改才能使其正常工作。 1) 我在employeeService.list(...) 方法中有一个pageIndex 参数。我想首先我将其设置为初始值 1,然后为每个循环增加它。 2) 我认为我们需要在订阅中累积返回值。但我不确定什么是最好的方法。任何想法?也许传播等。
    • 我还更新了方法,添加了pageIndex paraeter
    【解决方案2】:

    一个可能的解决方案:

    你可能想要扩大和缩小:

    我假设页面索引从 0 开始,您在“展开”之前开始的页面索引必须比您服务中的第一个页面索引小 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 是 Promise 的超集。由于第三方库没有期望 Promise,因此永远需要将 Observable 转换为 Promise。

    【讨论】:

    • 非常感谢,我会尽力通知您结果。我应该使用toPromise()subscribe 来填充下拉列表(对于本示例和其他情况,一次填充所有下拉列表)?
    • 一般来说,混合 observable 和 Promise 是一种代码味道。除非您使用的库需要/返回其中之一,否则我不会在两者之间进行转换。
    • 我试过你的方法,但reduce((acc, items) => ([...acc, ...items])) 行抛出 "core.js:4352 ERROR TypeError: items is not iterable" 错误。有什么想法吗?
    • 我认为 items 是一个数组,除了您在问题中写/显示的内容之外,我无法查看/提供任何建议。只需修改代码以满足您的需要:)
    • You rock!.. 它就像一个魅力,错误似乎是由于在第一步错误地设置了isComplete 值引起的。非常感谢:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-04
    • 1970-01-01
    • 2015-01-13
    • 2017-08-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多