我进行了搜索,但找不到答案:-(.。我确定解决方案与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调用?
答案 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需要花费时间,最好的入门方式始终是文档!