【问题标题】:RxJS: How to delay next emitted value?RxJS:如何延迟下一个发出的值?
【发布时间】:2021-11-08 17:14:07
【问题描述】:

我有异步函数handleParamsChanges,它可能需要几秒钟才能解决。我在 observable 发出值时调用它:

this._activatedRoute.params
  .subscribe(params => {
    this.handleParamsChanges(params).then(() => {
      // new value can be processed now
    });
  });

如何修改我的代码,以便如果 observable 一个接一个地发出 2 个值,第一个值调用 handleParamsChanges,并且只有 这个承诺解决之后,它被调用第二个值,等等。

编辑:

这是我想出的解决方案,但我猜有更好的方法来做到这一点:

const params$ = this._activatedRoute.params;
const canExecute$ = new BehaviorSubject(true);

combineLatest(params$, canExecute$)
  .pipe(
    filter(([_, canExecute]) => canExecute),
    map(([params]) => params),
    distinctUntilChanged()
  )
  .subscribe(async params => {
    canExecute$.next(false);
    try {
      await this.handleParamsChanges(params);
    } catch (e) {
      console.log(e);
    } finally {
      canExecute$.next(true);
    }
  })

我正在使用canExecute$ 来延迟新值的处理。

我需要在这里使用distinctUntilChanged 以避免创建无限循环。

【问题讨论】:

  • 为什么在处理下一个值之前需要等待handleParamsChanges 完成?
  • 我正在该函数中获取数据并更新我的视图。无需等待,如果一个接一个地发出两个值,则我为第二个值发出的 http 请求可能在第一个值之前完成,这样我就会显示错误的数据。

标签: javascript angular rxjs


【解决方案1】:

您正在寻找的是concatMap。在再次订阅之前,它会等待先前的“内部可观察”完成。您还可以大大简化您的管道:

params$.pipe(
  concatMap(params => this.handleParamsChanges(params)),
).subscribe()

【讨论】:

  • 我认为 switchMap 可能更合适?这个想法是丢弃陈旧的值,因此取消正在进行的请求并尽快(无需等待)获得新值是有意义的
  • 没关系。 HandleParamChnages 是一个承诺,因此无法取消。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-02
  • 1970-01-01
  • 1970-01-01
  • 2019-10-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多