不确定在哪里订阅 3 个与 switchMap 链接的 observables

Posted

技术标签:

【中文标题】不确定在哪里订阅 3 个与 switchMap 链接的 observables【英文标题】:Unsure where to put subscription for 3 observables chained with switchMap 【发布时间】:2020-08-08 03:39:28 【问题描述】:
this._authService.loggedInUser$.pipe(switchMap((loggedInUser: LoggedInUser) => 
      return this._userSerialService.getUserSerial().pipe(switchMap(serial => 
          return this._usersService.getCurrentUser().pipe(switchMap(currentUser => [loggedInUser, currentUser, serial]));
        ),
      );
    )).subscribe(([loggedInUser, currentUser, serial]) => 

    );

上面的代码尝试将 3 个 observable 链接在一起,并使用 switchMaps 将它们的结果映射到一个数组。在我的最终订阅中,我需要所有三个 observable 的结果值。但是,当我尝试以上面显示的方式订阅时,我收到了一个编译器错误,提示“Type 'LoggedInUser' must have a 'Symbol.iterator' method that return an iterator。

如果我使用subscribe(res => ,那么 res 最终只是 loggedInUser 的值,而不是全部三个值。

我需要在我的代码中进行哪些更改以确保我可以访问订阅中的所有三个值?

【问题讨论】:

【参考方案1】:

它看起来不像 switchMap 是你需要的。 switchMap 用于在底层“切换”源 observable,以便新的 observable 可以发射到流中。它处理从以前的来源取消订阅并订阅新的来源。

在您的情况下,您可以简单地使用combineLatest。一旦所有源 observables 都发出了一个值,这将发出一个包含所有 3 个值的数组,并且只要它们中的任何一个接收到新值,它将继续发出。

authUser$ = this._authService.loggedInUser$;
serial$   = this._userSerialService.getUserSerial();
user$     = this._usersService.getCurrentUser();

data$ = combineLatest([authUser$, serial$, user$]);


data$.subscribe(([loggedInUser, serial, currentUser]) => 
    ...
);

将值映射到对象会很方便,因此很容易在模板中检索它们,例如:

data$ = combineLatest([authUser$, serial$, user$]).pipe(
    map(([authUser, serial, user]) => (authUser, serial, user))
);

如果您在模板中使用 async pipe 而不是在组件中订阅,这也很方便。

<div *ngIf="data$ | async as data">
    <ul>
        <li>Current User:  data.user </li>
        <li>Logged in User:  data.authUser </li>
        <li>User Serial:  data.serial </li>
    </ul>
</div>

【讨论】:

【参考方案2】:

switchMap 运算符接受一个返回Observable 的函数,然后订阅它。 这里的问题是你的最后一个switchMap 得到一个数组而不是Observable。 您可以改用map 来转换数据。

this._authService.loggedInUser$.pipe(
  switchMap(loggedInUser => this._userSerialService.getUserSerial().pipe(
    switchMap(serial => this._usersService.getCurrentUser().pipe(
      map(currentUser => [loggedInUser, currentUser, serial]))
    )
  ))
).subscribe(([loggedInUser, currentUser, serial]) => 
  ...
);

【讨论】:

以上是关于不确定在哪里订阅 3 个与 switchMap 链接的 observables的主要内容,如果未能解决你的问题,请参考以下文章

使用SwitchMap()处理取消先前的请求

typescript 将switchMap()与嵌套订阅调用进行比较。

了解rxjs中的SwitchMap

为啥 switchMap 在 Angular 拦截器(Angular 9)中不起作用

RxJS mergeMap和switchMap

检查两个链表是不是合并。如果有,在哪里?