首页 > 解决方案 > 如何使用异步操作维护订阅者的顺序

问题描述

我有一个订阅其路由参数的角度组件。每当路由参数发生变化时,它都会从参数中读取id并调用一个函数来查找该 id 的记录。该函数返回一个承诺。解析后,组件为自己设置一个属性以进行数据绑定。

在某些情况下,响应似乎乱序,并且设置了错误的值。这是它的样子:

ngOnInit() {
  this.route.params.subscribe((params) => {
    const id = params['id'];
    console.log('processing', id);
    this.service.getPerson(id).then((person) => {
      console.log('processed id', id);
      this.person = person; // sometimes this happens out of order
    }
  }
}

因此,假设我有一个按名称过滤的文本框,当我键入时,导航事件会发生在id获得该名称的第一个结果的位置。有时我会看到:

处理 1

处理 2

处理 2

已处理 1 <---- 问题

解决这个问题的最优雅的方法是什么?我考虑过将 promise 转换为 observable 并尝试取消它,但这似乎很严厉。我试图弄清楚是否有一种方法可以序列化订阅,以便第二个“处理”在第一个完成之前不会开始。

标签: javascriptangulartypescriptrxjs

解决方案


您将要使用其中一个concatMapswitchMap. concatMap将确保在执行下一个请求之前完成前一个请求的处理。switchMap还将确保顺序,但如果在下一个请求到来时它仍在处理,它将中止对先前请求的处理。

ngOnInit() {
  this.route.params.pipe(
      map(params => params['id']),
      tap(id => console.log('processing', id)),
      concatMap(id => fromPromise(this.service.getPerson(id)).pipe(
        tap(person => console.log('processed id', id))
      )), 
      tap(person => this.person = person)
  )
  .subscribe();
}

推荐阅读