我正在关注此示例:https://www.intertech.com/Blog/angular-4-tutorial-handling-refresh-token-with-new-httpinterceptor/
除方法handle401Error
外,一切正常。除非我在拦截器中添加subscribe
,否则它不会执行。我必须遗漏一些东西,即使试图遵循这个例子。
以下是相关代码:
组件:
ngOnInit() {
this.service.getData()
.subscribe((response: any) => {
this.message = `Worked with status = ${response.status}`;
},
error => this.message = `Failed with status = ${error.status}`);
}
服务:
constructor(private http: HttpClient) {
this.currentToken = this.authTokenStale;
}
public authTokenStale: string = 'stale_auth_token';
public authTokenNew: string = 'new_auth_token';
public currentToken: string;
getData() {
return this.http.get<{status}>('https://private-4002d-testerrorresponses.apiary-mock.com/getDataError401');
}
getAuthToken() {
return this.currentToken;
}
refreshToken(): Observable<string> {
this.currentToken = this.authTokenNew;
return Observable.of(this.authTokenNew).delay(200);
}
拦截器:
isRefreshingToken: boolean = false;
tokenSubject: BehaviorSubject<string> = new BehaviorSubject<string>(null);
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
console.log('interceptor fired!')
let service = this.inj.get(Service);
// addToken() returns headers, getAuthToken() returns token
return next.handle(this.addToken(request, service.getAuthToken())).do((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
// success
}
}, (err: any) => {
if (err instanceof HttpErrorResponse) {
if (err.status === 401) {
return this.handle401Error(request, next);
}
}
});
}
handle401Error:
handle401Error(req: HttpRequest<any>, next: HttpHandler) {
if (!this.isRefreshingToken) {
this.isRefreshingToken = true;
let service = this.inj.get(Service);
this.tokenSubject.next(null);
return service.refreshToken()
.switchMap((newToken: string) => {
console.log('goes to switchMap') // does not come here!
if (newToken) {
this.tokenSubject.next(newToken);
return next.handle(this.addToken(this.getNewRequest(req), newToken));
}
return this.logoutUser();
})
.catch(....)
//.subscribe(() => {) // only works!
.finally(() => {
console.log('goes to finally')
this.isRefreshingToken = false;
});
} else {
return this.tokenSubject
.filter(token => token != null)
.take(1)
.switchMap(token => {
return next.handle(this.addToken(this.getNewRequest(req), token));
});
}
}
抱歉,有点代码,但我认为所有相关内容都能重现这个问题。
我也做了一个
展示问题!
答案 0 :(得分:6)
如果使用Angular 6,请记住有关RxJS库中的更改。
在新的RxJS中,使用do
运算符
next.handle(req).do(() => {});
必须更改为:
next.handle(req).pipe(tap(() => {}));
查看本文以获取更多信息:
答案 1 :(得分:1)
我通过将逻辑从catch
移到return next.handle(authReq).catch((err: any) => { //<--if error use a catch
if (err instanceof HttpErrorResponse) {
if (err.status === 401) {
//use switchMap to really return next.handle(authReq)
return auth.refreshToken().switchMap((value: any) => {
let httpHeaders = new HttpHeaders()
.set('Content-Type', 'application/json; charset=utf-8')
.set('Authorization', '' + auth.getAuthToken())
const authReq = req.clone({ headers: httpHeaders });
return next.handle(this.getNewRequest(req));
})
};
}
//Other case throw an error
return Observable.throw(err);
});
而不是https://stackoverflow.com/a/47420967/7741865来解决这个问题
.env