首页 > 解决方案 > 使用 NgRx 和拦截器的循环依赖警告

问题描述

我在我的拦截器中添加了一个调度来检查用户令牌是否过期以将它们注销,但由于某种原因,我收到了很多关于循环依赖的警告。

// Angular
import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse } from '@angular/common/http';
import { NavigationEnd, Router } from '@angular/router';
// RxJS
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
// import { debug } from 'util';
// NGRX
import { Store } from '@ngrx/store';
// State
import { AppState } from '../../../../core/reducers';
import { Logout } from '../../../../core/auth/';

@Injectable()
export class InterceptService implements HttpInterceptor {
    constructor(private store: Store<AppState>) {}
    // intercept request and add token
    intercept(
        request: HttpRequest<any>,
        next: HttpHandler
    ): Observable<HttpEvent<any>> {
        // tslint:disable-next-line:no-debugger
        // modify request
        request = request.clone({
            setHeaders: {
                Authorization: `${localStorage.getItem('authToken')}`
            }
        });
        // console.log('----request----');
        // console.log(request);
        // console.log('--- end of request---');

        return next.handle(request).pipe(
            tap(
                event => {

                     if (event instanceof HttpResponse) {
                        // console.log('all looks good');
                        // http response status code
                         console.log(event.status);
                    }
                },
                error => {
                    // http response status code
                    // console.log('----response----');
                    // console.error('status code:');
                    // tslint:disable-next-line:no-debugger
                    // console.error(error.status);
                    console.error(error.error.error);
                    if (error.error.error !== undefined && error.error.error.includes('Expired Token')) {
                        alert('You have been logged out due to signing in from another');
                        this.store.dispatch(new Logout());
                    }
                    // console.log('--- end of response---');
                }
            )
        );
    }
}
在此处输入图像描述

代码可以正常工作,但我不知道我是否应该意识到这些问题。我在注销组件上使用了完全相同的结构,并且没有问题。我假设是因为它是一项服务?

// auth.effect.ts

// Angular
import { Injectable } from '@angular/core';
import { NavigationEnd, Router } from '@angular/router';
// RxJS
import { filter, mergeMap, tap, withLatestFrom } from 'rxjs/operators';
import { defer, Observable, of } from 'rxjs';
// NGRX
import { Actions, Effect, ofType } from '@ngrx/effects';
import { Action, select, Store } from '@ngrx/store';
// Auth actions
import { AuthActionTypes, Login, Logout, Register, UserLoaded, UserRequested } from '../_actions/auth.actions';
import { AuthService } from '../_services/index';
import { AppState } from '../../reducers';
import { environment } from '../../../../environments/environment.prod';
import { isUserLoaded } from '../_selectors/auth.selectors';

@Injectable()
export class AuthEffects {

    @Effect({dispatch: false})
    logout$ = this.actions$.pipe(
        ofType<Logout>(AuthActionTypes.Logout),
        tap(() => {
            localStorage.removeItem(environment.authToken);
            this.router.navigate(['/auth/login'], {queryParams: {returnUrl: this.returnUrl}});
        })
    );

    private returnUrl: string;

    constructor(private actions$: Actions,
        private router: Router,
        private auth: AuthService,
        private store: Store<AppState>) {

        this.router.events.subscribe(event => {
            if (event instanceof NavigationEnd) {
                this.returnUrl = event.url;
            }
        });
    }
}

//auth.reducer.ts

// Actions
import { AuthActions, AuthActionTypes } from '../_actions/auth.actions';
// Models
import { User } from '../_models/user.model';

export interface AuthState {
    loggedIn: boolean;
    authToken: string;
    user: User;
    isUserLoaded: boolean;
}

export const initialAuthState: AuthState = {
    loggedIn: false,
    authToken: undefined,
    user: undefined,
    isUserLoaded: false
};

export function authReducer(state = initialAuthState, action: AuthActions): AuthState {
    switch (action.type) {
        case AuthActionTypes.Logout:
            return initialAuthState;


        default:
            return state;
    }
}

//auth.actions.ts

import { Action } from '@ngrx/store';
import { User } from '../_models/user.model';

export enum AuthActionTypes {
    Logout = '[Logout] Action'
}

export class Logout implements Action {
    readonly type = AuthActionTypes.Logout;
}


export type AuthActions = Logout;

// ../core/reducers/index.ts

// NGRX
import { ActionReducerMap, MetaReducer } from '@ngrx/store';
import { storeFreeze } from 'ngrx-store-freeze';
import { routerReducer } from '@ngrx/router-store';

import { environment } from '../../../environments/environment.prod';

// tslint:disable-next-line:no-empty-interface
export interface AppState { }

export const reducers: ActionReducerMap<AppState> = { router: routerReducer };

export const metaReducers: MetaReducer<AppState>[] = !environment.production ? [storeFreeze] : [];

标签: angularngrxinterceptorcircular-dependencyngrx-store

解决方案


推荐阅读