【问题标题】:Problem with successive async functions in AngularAngular中连续异步函数的问题
【发布时间】:2019-11-25 10:01:04
【问题描述】:

getEnrolledPlayers 应该从数据库中获取一个“玩家”对象数组,然后将其传递给 matchMaking 函数。但是,它没有正确通过。

我尝试添加 observables,玩转订阅

initializeEvent(eventId: string) {
  const enrolledPlayers: PlayerStat[] = [];
  this.getEnrolledPlayers(eventId)
    .subscribe((playerIds: string[]) => {
      for (const playerId of playerIds) {
        this.dataService.fetchSinglePlayer(playerId)
          .subscribe((playerStat: PlayerStat) => enrolledPlayers.push(playerStat));
      }
      this.matchMaking(enrolledPlayers);
    });
}

当我调用这一系列异步函数时,注册玩家[] 被正确计算(7 个元素的数组),但它没有被正确调用到 matchMaking() 函数。我认为这是因为异步运行时。

【问题讨论】:

  • ` this.matchMaking(enrolledPlayers);` 应该在你的内部subscribe() 函数中
  • @HaifengZhang 你mergeMap会更好

标签: javascript typescript asynchronous rxjs observable


【解决方案1】:

是的。这绝对是由于内部subscription解析值的时间差异造成的问题。

我建议使用forkJoin 并等待解决所有值,然后再调用matchMaking

试试这个:

initializeEvent(eventId: string) {
  const enrolledPlayers: PlayerStat[] = [];
  this.getEnrolledPlayers(eventId)
    .subscribe((playerIds: string[]) => {
      const playerInfos$ = playerIds.map(playerId => this.dataService.fetchSinglePlayer(playerId));
      forkJoin(...playerInfos$)
        .subscribe(enrolledPlayers: PlayerStat[] => this.matchMaking(enrolledPlayers));
    });
}

或者用一个subscribe

initializeEvent(eventId: string) {
  const enrolledPlayers: PlayerStat[] = [];
  this.getEnrolledPlayers(eventId)
    .take(1)
    .switchMap((playerIds: string[]) => {
      const playerInfos$ = playerIds.map(playerId => this.dataService.fetchSinglePlayer(playerId).take(1));
      return forkJoin(...playerInfos$);
    })
   .tap(this.matchMaking)
    .subscribe();
}

【讨论】:

  • 单次订阅是正确的答案。嵌套订阅是一种反模式。但你应该用 rxjs 6+ 语法回答这个问题
  • 完全同意@bryan60。
【解决方案2】:

这是一个嵌套订阅反模式......你永远不会嵌套订阅,这是使用高阶运算符的外观:

initializeEvent(eventId: string) {
  this.getEnrolledPlayers(eventId)
    .pipe(
      switchMap(playerIds => 
         forkJoin(playerIds.map(playerId => this.dataService.fetchSinglePlayer(playerId)))
      )
    ).subscribe((enrolledPlayers) => 
      this.matchMaking(enrolledPlayers)
    );
}

使用switchMap切换到一个新的observable,然后forkJoin并行运行多个observable

【讨论】:

    猜你喜欢
    • 2017-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-28
    • 2020-03-26
    • 1970-01-01
    • 1970-01-01
    • 2019-04-11
    相关资源
    最近更新 更多