HttpClient拦截器强制请求重复项 [英] HttpClient Interceptor forces request duplicates

查看:202
本文介绍了HttpClient拦截器强制请求重复项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我喜欢拥有一个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()和subscribe()之间的区别

修改

导入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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆