Angular 7-连续的http调用不起作用(管道,地图)

时间:2019-03-27 09:35:29

标签: javascript angular rxjs

我进行了搜索,但找不到答案:-(.。我确定解决方案与ConcatMap或类似内容有关,但我感到困惑。这是我的代码:

login(email: string, password: string): Observable<User> {
    const body = new HttpParams()
        .set('email', email)
        .set('password', password);

        return this.http.post<User>(LOGINSERVER, body.toString(),
        {
          headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded')
        })
        .pipe(map(user => {
            // login successful if there's a jwt token in the response
            if (user && user.accessToken) {
                // store user details and jwt token in local storage to keep user logged in between page refreshes
                localStorage.setItem('currentUser', JSON.stringify(user));
                this.currentUserSubject.next(user);

// now go get second set of credentials, the CloudCredentials using the bearer token returned by the first call
                this.http.get<CloudCredential[]>(CLOUDSERVER,
                {
                  headers: new HttpHeaders().set('Authorization', 'Bearer ' + user.accessToken)
                })
                .pipe(map(credentials => {
                    if (credentials) {
                        localStorage.setItem('cloudCredentials', JSON.stringify(credentials));
                        this.cloudCredentialsSubject.next(credentials);
                    }
                }));
    
                    
            }
            return user;
        }));
    }

所以发生的是对LOGINSERVER的 first http调用起作用了!太好了:-)但是,当该调用完成时,Chrome调试器将显示对CLOUDSERVER进行 second http调用的行,但该API端点实际上从未运行。处理上面第二个结果集行的.pipe.map()永远不会被调用/执行。

我的总体目标是使上面的login()方法返回可观察到的“用户”,并且还为该方法设置局部变量currentUserSubject和cloudCredentialsSubject这些可观察值的值,以便以后可以从其他对象中引用它们。该应用程序。

所以问题是:即使我看到正在执行的代码行,为什么也没有进行 second http调用?只有在第一个调用成功的情况下,我该怎么做才能执行第二个http调用?

1 个答案:

答案 0 :(得分:3)

这是正确的语法:

return this.http.post<User>(LOGINSERVER, body.toString(), { headers: new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded') }).pipe(
  switchMap(user => {
    if (user && user.accessToken) {
      localStorage.setItem('currentUser', JSON.stringify(user));
      this.currentUserSubject.next(user);

      return this.http.get<CloudCredential[]>(CLOUDSERVER, { headers: new HttpHeaders().set('Authorization', 'Bearer ' + user.accessToken) }).pipe(
        tap(credentials => {
          if (credentials) {
            localStorage.setItem('cloudCredentials', JSON.stringify(credentials));
            this.cloudCredentialsSubject.next(credentials);
          }
        })
      );
    } else {
      return throwError('User is not defined or has no access Token');
    }
  })
);

map用于转换流的值,而switchMap用于将流与另一流切换。 tap用于执行不修改流的操作。 throwError引发错误,然后可以用catchError运算符捕获该错误:它不会引发错误本身,而是允许您将有效流切换到无效,进入subscribe函数的第二个回调。

您可以在这里找到有关运算符的所有信息:https://www.learnrxjs.io/operators/

学习RxJS需要花费时间,最好的入门方式始终是文档!