在401响应中完全忽略CatchError.
我有httpInterceptor处理oauth2身份验证.
相关代码是:
import { filter, take, switchMap, map, catchError } from 'rxjs/operators';
//ommited
if (authService.hasRefreshToken()) {
return authService.doRefreshToken().pipe(switchMap(tokenResponse => {
const accessToken = tokenResponse['access_token'];
this.tokenSubject.next(accessToken);
return <Observable<HttpEvent<any>>> next.handle(this.addToken(req, accessToken));
}), catchError((err: any, caught: any) => {
console.log(err)
return Observable.throw(err);
})
)
}
Run Code Online (Sandbox Code Playgroud)
AuthService类:
export class AuthService {
doRefreshToken() {
//ommited
return this.httpClient.post(environment.baseUrl + this.tokenEndpoint, null, requestOptions).pipe(
map(tokenResponse => {
this.saveToken(tokenResponse);
return tokenResponse;
}),
catchError((err: any, caught: Observable<Object>) => {
//refreshing token failed (refrech token invalid or expired) redirect to login and wipe everything
this.logout();
return Observable.throw(err);
}));
}
}
Run Code Online (Sandbox Code Playgroud)
一切正常200响应,但401错误完全被忽略.我使用这个新的catch错误方式吗?
PS这段代码工作得很好用普通的旧捕获,但现在当我迁移到angular6管道和catchError相同的东西只是不起作用.
编辑:
catchError上的断点显示
"SyntaxError:AuthService.push的输入意外结束../src/app/common/auth/auth.service.ts.AuthService.doRefreshToken
服务器的实际响应是:
{
"error" : "invalid_token",
"error_description" : "Refresh token expired"
}
Run Code Online (Sandbox Code Playgroud)
标题:
Request Method: POST
Status Code: 401
Run Code Online (Sandbox Code Playgroud)
我遇到了同样的问题,该catchError功能被完全忽略。由于@SeaBiscuit 使用官方Angular 文档中描述的简单直接的代码不起作用,因此我放弃了这种处理错误响应的方法,而是查看了 HttpInterceptors。这奏效了!
我受到 Luuk Gruijs 在他的文章《Angular 4.3+ 中捕获全局 HTTP 错误》中的指导的启发,将下面所示的内容添加ErrorInterceptor到我的代码中。
诚然,下面的拦截器可能并不完美,但是拦截器中处理错误的最重要的部分可以归结为:
next.handle(request).pipe(tap(
(event: HttpEvent<any>) => { },
(error: any) => {
// Handle errors here!
}
))
Run Code Online (Sandbox Code Playgroud)
以下是我所实现的更详细的介绍:
export class ErrorInterceptor implements HttpInterceptor {
constructor() { }
intercept (request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
if (request.method !== 'GET') {
return next.handle(request);
}
const subject = new AsyncSubject<HttpEvent<any>>();
next.handle(request)
.pipe(
tap((event: HttpEvent<any>) => {
// Let HttpResponses pass through interceptor without interaction
if (event instanceof HttpResponse) {
subject.next(event);
subject.complete();
}
}, (error: any) => {
if (error instanceof HttpErrorResponse) {
const errorEvent = new HttpResponse({
body: {
message: error.error.message,
status: error.status,
statusText: error.statusText
}
});
subject.next(errorEvent);
subject.complete();
}
})
).subscribe();
return subject;
}
}
Run Code Online (Sandbox Code Playgroud)
我还修改了我的服务以接受手动创建的响应正文:
return this.http.get<MyObjI | ErrorI>(url, {params});
Run Code Online (Sandbox Code Playgroud)
... 哪里ErrorI:
export interface ErrorI {
message: string;
status: number;
statusText: string;
}
Run Code Online (Sandbox Code Playgroud)
希望拦截器中的错误处理也能帮到你!