HttpClient拦截器强制请求重复项 [英] HttpClient Interceptor forces request duplicates
问题描述
我喜欢拥有一个HttpInterceptor(角度6),它添加了授权标头,但也处理401以重定向到登录页面. 这是我的代码:
I like to have a HttpInterceptor (Angular 6), which adds Authorization Headers but also handles 401 to redirect to login page. This is my code:
import {Injectable} from '@angular/core';
import {HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {Observable} from 'rxjs';
import {Router} from '@angular/router';
@Injectable()
export class JwtInterceptor implements HttpInterceptor {
constructor(private router: Router) {
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// add authorization header with jwt token if available
let currentUser = JSON.parse(localStorage.getItem('currentUser'));
if (currentUser && currentUser.token) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${currentUser.token}`,
},
});
}
const req = next.handle(request);
// ---------------- VVV ---------------
req.subscribe(() => {
}, (error: any) => {
if (error instanceof HttpErrorResponse && (error as HttpErrorResponse).status === 401)
this.router.navigate(['public/login']);
});
// ---------------- ^^^ ---------------
return req;
}
}
一切正常,因为vvv/^^^注释中的代码强制将请求发送两次.为什么这个?好的,我可能必须订阅请求,因为此拦截器进行了订阅,并且可能使用了HttpClient服务. 有没有解决此问题的方法?
All works fine execpt that the code inside the vvv / ^^^ comment enforces that the request is sent twice. Why this? OK, I probably have to subscriptions on the request because this interceptor subscribes and probably my service using the HttpClient. Is there a bether way to solve this?
这是package.json中的依赖项:
...
"@angular/compiler": "6.0.3",
"@angular/core": "6.0.3",
"@angular/http": "6.0.3",
"@angular/router": "6.0.3",
"rxjs": "^6.2.0",
"rxjs-compat": "^6.2.0",
"rxjs-tslint": "^0.1.4",
"zone.js": "^0.8.26"
...
推荐答案
您应使用do()
而不是subscribe()
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// add authorization header with jwt token if available
let currentUser = JSON.parse(localStorage.getItem('currentUser'));
if (currentUser && currentUser.token) {
request = request.clone({
setHeaders: {
Authorization: `Bearer ${currentUser.token}`,
},
});
}
return next.handle(request).do((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
// do stuff with response if you want
}
}, (err: any) => {
if (err instanceof HttpErrorResponse {
if (err.status === 401) {
this.router.navigate(['public/login']);
}
}
});
}
修改
导入do
运算符import { do } from 'rxjs/operators';
为什么用作订阅时忽略/点击?
此处的要点是,与其他运算符不同,do()
不会影响流的流.它接受响应,执行某些操作,即使它修改了响应,流也将忽略它.当您尝试将其用作subscribe()
时,它已被忽略,因为您已经在下面的语句中返回了流
The point here is that do()
will not affect the flow of the stream, unlike other operators. It takes the response, does something and even if it modifies the response the stream is going to ignore it. When you try to use it as subscribe()
it simply get's ignored as you have already returned stream in below statement
这篇关于HttpClient拦截器强制请求重复项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!