为什么 switchMap 在 Angular 拦截器(Angular 9)中不起作用

why switchMap not working in Angular interceptor ( Angular 9 )

我写了一个拦截器来为我刷新令牌。但是用我查的调试器,根本就没有进入switchMap,请求也没有再发送。 有谁知道问题出在哪里?

    import {HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse} from '@angular/common/http';
import {Injectable, Injector} from '@angular/core';
import {BehaviorSubject, Observable} from 'rxjs';
import {catchError, switchMap, tap} from 'rxjs/operators';
import {ResponseModel} from '../Models/responseModel';
import {UserDataModel} from '../Models/UserDataModel';
import {RoleEnum} from '../Enums/RoleEnum';
import {AuthService} from '../../auth/auth.service';
import {AuthModel} from '../Models/authModel';
import {LoginType} from '../Enums/LoginType';
import {LoginResponseModel} from '../Models/LoginResponseModel';

@Injectable({providedIn: 'root'})
export class TokenInterceptor implements HttpInterceptor {
    httpSubject: BehaviorSubject<LoginResponseModel> = new BehaviorSubject<LoginResponseModel>(null);

    constructor(private injector: Injector) {
    }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        let modifiedReq;
        const userData: {
            username: string,
            access_token: string,
            refresh_token: string,
            role: RoleEnum,
            _tokenexpirationDate: string
        } = (JSON.parse(localStorage.getItem('userData')));
        if (userData.access_token !== null && !req.headers.has('X-Skip-Interceptor')) {
            modifiedReq = req.clone({
                headers: req.headers.set('access_token', `${userData.access_token}`),
            });
        } else {
            modifiedReq = req.clone({
                setHeaders: {
                    'Content-Type': 'application/json',
                    'Access-Control-Allow-Origin': '*'
                }
            });
        }
        return next.handle(modifiedReq).pipe(tap(res => {
            if (res instanceof HttpResponse) {
                const response = (<HttpResponse<ResponseModel<string>>> res).body;
                /*const userdata: {
                    username: string,
                    access_token: string,
                    refresh_token: string,
                    role: RoleEnum,
                    _tokenexpirationDate: string
                } = (JSON.parse(localStorage.getItem('userData')));*/
                if (!response.is_successfull) {
                    if (new Date() > new Date(userData._tokenexpirationDate)) {
                        this.refreshToken(req, next, userData.refresh_token, userData.username);
                    }
                }
            }
        }));
    }

    refreshToken(req: HttpRequest<any>, next: HttpHandler, refreshtoken: string, username: string) {
        this.httpSubject.next(null);
        const authService = this.injector.get(AuthService);
        const authmodel: AuthModel = {
            email_address: '', grant_type: LoginType.RefreshToken, password: '', phone_number: '', phone_number_countery_iso2_code: '',
            refresh_token: refreshtoken, username: ''
        };

        debugger;
        return authService.Signin(authmodel).pipe(
            switchMap(result => {
                debugger;
                if (result.is_successfull && result.response.access_token !== null) {
                    const expirationDate = new Date(new Date().getTime() + +result.response.expires_in * 60000);
                    const user = new UserDataModel(username, result.response.access_token, result.response.refresh_token
                        , result.response.role, expirationDate);
                    localStorage.setItem('userData', JSON.stringify(user));
                    this.httpSubject.next(result.response);
                    req = req.clone({
                        setHeaders: {
                            access_token: `${result.response.access_token}`
                        }
                    });
                    return next.handle(req);

                }

            }) , catchError(err => {
                console.log(err);
                return Observable;
            }));
    }
}

我还要说一下,如果我用subscribe而不是pipe,switchMap的话,token会刷新,只有request不会从头重复

您的代码应该是:-

   import {HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse} from '@angular/common/http';
import {Injectable, Injector} from '@angular/core';
import {BehaviorSubject, Observable} from 'rxjs';
import {catchError, switchMap, tap} from 'rxjs/operators';
import {ResponseModel} from '../Models/responseModel';
import {UserDataModel} from '../Models/UserDataModel';
import {RoleEnum} from '../Enums/RoleEnum';
import {AuthService} from '../../auth/auth.service';
import {AuthModel} from '../Models/authModel';
import {LoginType} from '../Enums/LoginType';
import {LoginResponseModel} from '../Models/LoginResponseModel';

@Injectable({providedIn: 'root'})
export class TokenInterceptor implements HttpInterceptor {
    httpSubject: BehaviorSubject<LoginResponseModel> = new BehaviorSubject<LoginResponseModel>(null);

    constructor(private injector: Injector) {
    }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        let modifiedReq;
        const userData: {
            username: string,
            access_token: string,
            refresh_token: string,
            role: RoleEnum,
            _tokenexpirationDate: string
        } = (JSON.parse(localStorage.getItem('userData')));
        if (userData.access_token !== null && !req.headers.has('X-Skip-Interceptor')) {
            modifiedReq = req.clone({
                headers: req.headers.set('access_token', `${userData.access_token}`),
            });
        } else {
            modifiedReq = req.clone({
                setHeaders: {
                    'Content-Type': 'application/json',
                    'Access-Control-Allow-Origin': '*'
                }
            });
        }
        return next.handle(modifiedReq).pipe(tap(res => {
            if (res instanceof HttpResponse) {
                const response = (<HttpResponse<ResponseModel<string>>> res).body;
                /*const userdata: {
                    username: string,
                    access_token: string,
                    refresh_token: string,
                    role: RoleEnum,
                    _tokenexpirationDate: string
                } = (JSON.parse(localStorage.getItem('userData')));*/
                if (!response.is_successfull) {
                    if (new Date() > new Date(userData._tokenexpirationDate)) {
                        this.refreshToken(req, next, userData.refresh_token, userData.username).then((request)=> {


                                   modifiedRequest = request.clone();
                                   throw "replay";
                     });
                    }
                }

        }),retryWhen(errors => errors);
    }

refreshToken(req: HttpRequest<any>, next: HttpHandler, refreshtoken: string, username: string) {
            this.httpSubject.next(null);
            const authService = this.injector.get(AuthService);
            const authmodel: AuthModel = {
                email_address: '', grant_type: LoginType.RefreshToken, password: '', phone_number: '', phone_number_countery_iso2_code: '',
                refresh_token: refreshtoken, username: ''
            };

            debugger;
            return await authService.Signin(authmodel).pipe(
                map(result => {
                    debugger;
                    if (result.is_successfull && result.response.access_token !== null) {
                        const expirationDate = new Date(new Date().getTime() + +result.response.expires_in * 60000);
                        const user = new UserDataModel(username, result.response.access_token, result.response.refresh_token
                            , result.response.role, expirationDate);
                        localStorage.setItem('userData', JSON.stringify(user));
                        this.httpSubject.next(result.response);
                        req = req.clone({
                            setHeaders: {
                                access_token: `${result.response.access_token}`
                            }
                        });
                        return req;

                    }

                }) , catchError(err => {
                    console.log(err);
                    return Observable;
                })).toPromise();
        }
    }

原因:- Tap 没有订阅您返回的内部可观察对象。 mergemap 就是这样做的。应使用适当的运算符进行流组合。