我的业务场景是这样的: 首先,我向WebAPI中的token()端点发出HTTP请求以获取身份验证令牌(这发生在app.component.ts中)。然后,我有一个令牌拦截器模块,将令牌附加到后续请求的HTTP标头中。
然后,我在WebAPI中有一个getLanguages()端点,并且在我的标头组件header.component.ts中调用了该端点。因此,此调用将通过HTTP拦截器进行尝试,并尝试将生成的令牌附加到请求标头中,但是由于token()端点尚未返回,因此getLanguages()端点未通过身份验证而失败。
我显然在这里丢失了一些东西。我已经读过ReplaySubject
的内容,但不确定如何将所有内容放在一起。
这是我当前的代码。
<app-header>
</app-header>
<router-outlet></router-outlet>
<app-footer>
</app-footer>
authenticateClient(){
let body = new HttpParams()
.set('client_id', AppConst.GLOBAL.auth.client_id)
.set('grant_type', AppConst.GLOBAL.auth.grant_type)
.set('scope', AppConst.GLOBAL.auth.scope);
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/x-www-form-urlencoded'
})
};
let authGatewayUrl: string = AppConst.GLOBAL.authApiUrl + window.location.search;
return this.http.post(authGatewayUrl, body.toString(), httpOptions)
.pipe(map((res: any) => this.token = res), catchError(this.handleErrorObservable));
}
getToken(): Token {
return this.token;
}
token: Token;
ngOnInit() {
// get the authentication token and store it for usage in subsequent API calls.
this.authService.authenticateClient().subscribe(
obj => this.token = obj as Token,
err => alert(err)
);
}
getLanguages() {
return this.http.get(this.localeApiUrl)
.pipe(map((res: any) => this.languages = res), catchError(this.handleErrorObservable));
}
constructor(private appService: AppService) {
this.appService.getLanguages().subscribe(obj => this.languages = obj);
};
intercept(req: HttpRequest<any>, next: HttpHandler) {
// exclude the token API endpoint from the interception
const loginUrl: string = AppConst.GLOBAL.authApiUrl;
if (req.url.search(loginUrl) === -1) {
// Get the auth token from the service.
const authToken = this.auth.getToken();
//// Clone the request and set the new header in one step.
req = req.clone({ setHeaders: { Authorization: authToken.access_token } });
}
//// send cloned request with header to the next handler.
return next.handle(req);
}
答案 0 :(得分:2)
您可以将令牌信息保存在AuthService内部的BehaviorSubject
中。
然后在.next(token)
成功时触发authenticateClient()
。
在header.component
中,您可以这样做。
readonly languages$ = this.authService.token$.pipe(
first(!!token), // or filter, depends on your application logic
switchMap(() => this.appService.getLanguages(),
);
this.languages$.subscribe(obj => this.languages = obj);
在上面的代码中,您将从authService创建一个新的Observable,当有人在令牌next
上触发BehaviorSubject
时,此Observable会检查是否已定义令牌,如果已定义,则可以调用您的内部API。
这是一种方法,但我认为还有其他解决方案。
答案 1 :(得分:-4)
您也可以使用Promise。
var promise = new Promise((resolve, reject) => {
setTimeout(() => {
console.log("Async Work Complete");
if (error) {
reject();
} else {
resolve();
}
}, 1000);
});