angular - Angular6 HttpClient catchError 不起作用
问题描述
CatchError 在 401 响应中被完全忽略。
我有处理 oauth2 身份验证的 httpInterceptor。
相关代码是:
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);
})
)
}
认证服务类:
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);
}));
}
}
200 响应一切正常,但 401 错误被完全忽略。我是否以错误的方式使用这个新的 catchError ?
PS 这段代码在普通的旧 catch 上工作得很好,但是现在当我迁移到 angular6 管道和 catchError 时,同样的东西就不起作用了。
编辑 :
catchError 上的断点显示
“语法错误:在 AuthService.push../src/app/common/auth/auth.service.ts.AuthService.doRefreshToken 输入意外结束
来自服务器的实际响应是:
{
"error" : "invalid_token",
"error_description" : "Refresh token expired"
}
标题:
Request Method: POST
Status Code: 401
解决方案
我有同样的catchError
功能被完全忽略的问题。由于官方Angular 文档中描述的 @SeaBiscuit 使用的这个简单直接的代码不起作用,我放弃了这种处理错误响应的方法,而是查看了 HttpInterceptors。那行得通!
Luuk Gruijs 在他的文章Global HTTP error catch in Angular 4.3+ 中的指导启发了我,将ErrorInterceptor
下面显示的内容添加到我的代码中。
诚然,下面的拦截器可能并不完美,但拦截器中处理错误的最重要部分归结为:
next.handle(request).pipe(tap(
(event: HttpEvent<any>) => { },
(error: any) => {
// Handle errors here!
}
))
这是我实施的更详细的一瞥:
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;
}
}
我还修改了我的服务以接受手动创建的响应正文:
return this.http.get<MyObjI | ErrorI>(url, {params});
...在哪里ErrorI
:
export interface ErrorI {
message: string;
status: number;
statusText: string;
}
希望在拦截器中处理错误也对您有用!
推荐阅读
- python - 在 python 中使用 enumerate() 和 takewhile() 返回一个列表
- python-3.x - 如何在 python 中使用 ffmpeg 压缩视频?
- javascript - 通过 php 和 curl 创建一个不和谐的邀请链接?
- sql - 如何重用插入语句的值
- full-text-search - 相关性分数如何在 memsql 的全文搜索中发挥作用?
- ios - 在 Swift 中 TabBarController 的选项卡之间共享数据/模型的最佳实践
- php - Phpmyadmin 触发器定义,用于在更改到另一个表时更新另一个数据库表上的特定列
- data-structures - 3阶B树的叶子数
- vba - 为什么循环在if语句的“else”处结束
- php - 如何删除已弃用的 Symfony\Component\Debug\DebugClassLoader?