我正在尝试更好地处理RXJS,但当我调用AudienceService.addAudience()时,我得到Cannot read property 'map' of undefined
。
问题似乎是当需要令牌刷新时,AudienceService
会在AuthHttpService.post()
内的订阅完成之前尝试映射到AuthHttpService.post()
。
我如何为此编码,并确保map()
仅在AuthHttpService
刷新令牌后才执行?
映射到AuthHttpService.post的AudienceService:
addAudience(model: AddDeleteAudienceModel) {
return this.authHttpService.post(this.baseApiUrl + 'audience', JSON.stringify(model)).map(res => res.json());
}
使用POST方法的AuthHttpService:
post(endpoint: string, body: string) {
if (this.authService.tokenRequiresRefresh()) {
this.authService.tokenIsBeingRefreshed.next(true);
this.authService.refreshToken().subscribe(
data => {
this.authService.refreshTokenSuccessHandler(data);
// The audience service post call returns "Cannot read property 'map' of undefined"
console.log("User is now logged in");
if (this.authService.loggedIn()) {
this.authService.tokenIsBeingRefreshed.next(false);
return this.postInternal(endpoint, body);
} else {
this.authService.tokenIsBeingRefreshed.next(false);
this.router.navigate(['/sessiontimeout']);
}
},
error => {
this.authService.refreshTokenErrorHandler(error);
Observable.throw(error);
}
);
}
else {
console.log("HTTP Post token refresh not required.");
return this.postInternal(endpoint, body);
}
}
答案 0 :(得分:4)
如前所述,post()
在需要刷新令牌时不会返回任何内容。在刷新令牌之前函数返回时,将不会调用return
方法中的subscribe()
语句。
您应该使用switchMap()
代替subscribe
来电。在这种情况下,您还需要从else块中返回一个Observable。像这样:
post(endpoint: string, body: string) {
if (this.authService.tokenRequiresRefresh()) {
this.authService.tokenIsBeingRefreshed.next(true);
return this.authService.refreshToken().switchMap(
data => {
this.authService.refreshTokenSuccessHandler(data);
// The audience service post call returns "Cannot read property 'map' of undefined"
console.log("User is now logged in");
if (this.authService.loggedIn()) {
this.authService.tokenIsBeingRefreshed.next(false);
return this.postInternal(endpoint, body);
} else {
this.authService.tokenIsBeingRefreshed.next(false);
this.router.navigate(['/sessiontimeout']);
// return an Observable here otherwise you also get an undefined
}
})
.catch((error) => {
this.authService.refreshTokenErrorHandler(error);
return Observable.throw(error);
});
}
else {
console.log("HTTP Post token refresh not required.");
return this.postInternal(endpoint, body);
}
}
有关switchMap()
的更多信息。它基本上将内部Observable的值映射到外部Observable。
答案 1 :(得分:1)
在Post中你需要返回observable。我不确定100%这是否有效,但想法是你创建了observable并返回它,而不是你在逻辑内部。您可以发出next,或抛出异常
post(endpoint: string, body: string) {
if (this.authService.tokenRequiresRefresh()) {
this.authService.tokenIsBeingRefreshed.next(true);
return Observable.create((observer) => {
this.authService.refreshToken().subscribe(
data => {
this.authService.refreshTokenSuccessHandler(data);
// The audience service post call returns "Cannot read property 'map' of undefined"
console.log("User is now logged in");
if (this.authService.loggedIn()) {
this.authService.tokenIsBeingRefreshed.next(false);
this.postInternal(endpoint, body).subscribe(resp => {
observer.next(resp);
})
} else {
this.authService.tokenIsBeingRefreshed.next(false);
this.router.navigate(['/sessiontimeout']);
observer.error(error);
}
},
error => {
this.authService.refreshTokenErrorHandler(error);
observer.error(error);
}
);
});
}
else {
console.log("HTTP Post token refresh not required.");
return this.postInternal(endpoint, body);
}
}
我已经测试了我的应用
的一部分return Observable.create(observer => {
(<Promise<string>>token)
.then((tAsString) => {
super.request(this.getRequestOptionArgs(tAsString, request))
.subscribe(response => {
observer.next(response);
// this emit error observer.error(eror)
})
})
});
PS。但我的事情是switchMap是更好的选择:)