首页 > 解决方案 > HttpInterceptor 在惰性模块中不起作用

问题描述

我已经创建了HttpInterceptor适用于 App 模块的应用程序模块,但是它不会被作为惰性模块的特色模块调用。我想知道为什么它不起作用。

  1. 我已经提供了HttpInterceptorin app.module.ts
  2. 我正在使用 Angular 7
  3. HttpClient正在使用的不是Http.

如果您需要其他详细信息,请告诉我。

应用模块

    @NgModule({
    declarations: [AppComponent],
    imports: [
        BrowserModule,
        BrowserAnimationsModule,
        HttpClientModule,
        AppRoutingModule,

        NgbModule.forRoot(),
        ThemeModule.forRoot(),
        CoreModule.forRoot(),
    ],
    bootstrap: [AppComponent],
    providers: [
        {provide: APP_BASE_HREF, useValue: '/'},
        AuthGuard,
        {
            provide: NbRoleProvider,
            useClass: RoleProvider,
        },
        ZtLoaderService
    ],
   })
    export class AppModule {
  }

核心模块

export class CoreModule {
    constructor(@Optional() @SkipSelf() parentModule: CoreModule) {
        throwIfAlreadyLoaded(parentModule, 'CoreModule');
    }

    static forRoot(): ModuleWithProviders {
        return <ModuleWithProviders> {
            ngModule: CoreModule,
            providers: [
                ...NB_CORE_PROVIDERS,
                httpInterceptorProviders
            ],
        };
    }
}

httpInterceptorProviders

export const httpInterceptorProviders = [

    {provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true},
    {provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true}

];

身份验证拦截器

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

    constructor(private injector: Injector) {
    }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        // do not intercept request whose urls are filtered by the injected filter
        console.log("intercept.........................");
        this.authService.isAuthenticatedOrRefresh().subscribe(response=>{
            console.log("authenticated ----------->", response);
        })
        return this.authService.isAuthenticatedOrRefresh()
            .pipe(
                switchMap(authenticated => {
                    if (authenticated) {
                        return this.authService.getToken().pipe(
                            switchMap((token: any) => {
                                const JWT = `Bearer ${token.getValue()}`;
                                req = req.clone({
                                    setHeaders: {
                                        Authorization: JWT,
                                    },
                                });
                                return next.handle(req);
                            }),
                        )
                    } else {
                        // Request is sent to server without authentication so that the client code
                        // receives the 401/403 error and can act as desired ('session expired', redirect to login, aso)
                        return next.handle(req);
                    }
                }),
            )

    }

    protected get authService(): NbAuthService {
        return this.injector.get(NbAuthService);
    }

}

惰性模块:BPOEntryModule

@NgModule({
    imports: [
        ThemeModule,
        BPORoutingModule,
        Ng2SmartTableModule
    ],
    declarations: [
        ...routedComponents,
        BlListEntry,
        EntryListSearchResultComponent,
        EntryListSearchComponent,
        ModalComponent,
        ResultItemComponent,
        ResultToolbarComponent
    ],
    entryComponents: [ModalComponent],

    providers: [BPOEntryService]
})
export class BPOEntryModule {}

标签: angularangular7

解决方案


我会检查延迟加载模块中的所有提供程序和组件,看看它们是否正在调用 HttpClient。如果它们是,这将是 HttpClient 的一个不同实例,而不是作为 AppModule 初始化的一部分构造的实例,因此不会附加拦截器。

我能想到几个解决方案,我的偏好是 B:

A) 在任何延迟加载的模块 IE 中重新附加拦截器:

@NgModule({
    imports: [
        ThemeModule,
        BPORoutingModule,
        Ng2SmartTableModule
    ],
    declarations: [
        ...routedComponents,
        BlListEntry,
        EntryListSearchResultComponent,
        EntryListSearchComponent,
        ModalComponent,
        ResultItemComponent,
        ResultToolbarComponent
    ],
    entryComponents: [ModalComponent],

    providers: [
        BPOEntryService,
        httpInterceptorProviders
    ]
})
export class BPOEntryModule {}

B) 把所有依赖HttpClient的服务都放到CoreModule里面(或者为http服务新建一个模块,并创建一个forRoot方法)。您现有的核心模块是如何编写的,它使用 forRoot 命令创建一个依赖服务的单例:

CoreModule.forRoot(),

由于它们是与您的 AppModule 一起作为单例创建的,因此它们应该将 AppModule 中的 HttpInterceptor 附加到 HttpClient 实例。延迟加载的模块支持 forRoot() 单例模式,因此这些服务也应该可用于任何延迟加载的模块。

在这里阅读更多关于单身人士https://angular.io/guide/singleton-services


推荐阅读