【问题标题】:RxJs Observable forkJoinRxJs Observable forkJoin
【发布时间】:2018-05-01 23:57:01
【问题描述】:

我正在使用 Angular 5 (RxJs 5.5.1) 编写服务,并且在以下场景中我正在尝试实现登录工作流。

...
signInBasic(user: string, pwd: string): Observable<AuthenticationStatus> {
    return this.http.post('some_url', params, { observe: 'response', responseType: 'text' })
      .map((response: HttpResponse<Object>) => {
        this.status = response.status === 200 ? AuthenticationStatus.Authenticated : AuthenticationStatus.NotAuthenticated;
        return this.status;
      })
      ...
      /* HERE */
      ...

}

getPrimaryInfo(): Observable<any> {}
getPermissions(): Observable<any> {}
...

/* HERE */ 点,取决于this.status 值(特别是Authenticated)我想再触发两个HTTP 请求(通过getPrimaryInfogetPermissions 方法),以便从中获取一些用户的详细信息后端。两者都完成后,我想将this.status 作为signInBasic 方法的返回值返回。如果用户未通过身份验证,我无论如何都会返回 this.statusAuthenticationStatus.NotAuthenticated 值,因为它是之前设置的。

我一直在寻找 forkJoin,但我不明白只有在这两个 HTTP 调用完成后才能返回一些东西。

【问题讨论】:

    标签: angular rxjs


    【解决方案1】:

    无论两个请求返回什么,您都可以使用concatMap 等待forkJoin 完成,然后将结果映射到this.status

    signInBasic(user: string, pwd: string) {
      return this.http.post('some_url', params, ...)
        .concatMap((response: HttpResponse<Object>) => {
          this.status = response.status === 200 ? AuthenticationStatus.Authenticated : AuthenticationStatus.NotAuthenticated;
    
          if (this.status === AuthenticationStatus.Authenticated) {
            return forkJoin(getPrimaryInfo(), getPermissions())
              .pipe(
                map(() => this.status),
              );
          } else {
            return of(this.status);
          }
        });
    }
    

    【讨论】:

    • 这会将值发送两次,这可能不是预期的行为。这是带有投影功能的switchMap的情况
    • 为什么会发送两次?
    • 因为 concatMap 发出源值和内部值
    • 不,它没有。它只从内部 Observable 发出值,因为它希望您将源 Observable 中的值“映射”到另一个 Observable。
    • 我的错误,把它和普通的 concat 混淆了
    【解决方案2】:

    在这种情况下,带有投影功能的 switchMap 是你的朋友:

    return this.http.post('some_url', params, { observe: 'response', responseType: 'text' })
      .map((response: HttpResponse<Object>) => {
        this.status = response.status === 200 ? AuthenticationStatus.Authenticated : AuthenticationStatus.NotAuthenticated;
        return this.status;
      })
      .switchMap(status => (status === AutheticationStatuses.Authenticated)
                              ? forkJoin(getPrimaryInfo(), getPermissions())
                              : of(null),
                 (status, inner) => status);
    

    【讨论】:

    • 感谢您的回答,非常感谢。
    猜你喜欢
    • 2018-10-02
    • 1970-01-01
    • 2021-03-25
    • 2018-12-06
    • 2021-03-27
    • 1970-01-01
    • 1970-01-01
    • 2020-02-26
    • 2021-03-10
    相关资源
    最近更新 更多