Boshra N
Boshra N

Reputation: 111

Angular 9: interceptor cyclic dependency while injecting lazy loaded service

I face Cannot instantiate cyclic dependency! InjectionToken HTTP_INTERCEPTORS error while injecting my lazy loaded service in the interceptor.

However, so strange my problem is being solved by adding an empty setTimeout(() to the service injection in the interceptor. I am wondering why that happens though...

the lazy loaded LanguageService:

import { HttpClient } from '@angular/common/http';
@Injectable()

export class LanguageService {

  constructor(private http: HttpClient,
    private _translate: TranslateService) {
    this.getLanguages();
  }
// ....

the interceptor:

import { Injectable, Injector } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler } from '@angular/common/http';
import { LanguageService } from '../app/blog/services/language.service';

@Injectable()

export class LanguageInterceptor implements HttpInterceptor {
    private _languageService:LanguageService;

    constructor(private injector: Injector) {
        /*  This way Works!
            setTimeout(() => {
            this._languageService = this.injector.get(LanguageService)
         })*/

      
            this._languageService = this.injector.get(LanguageService)
         
    }
    
    intercept(req: HttpRequest<any>, next: HttpHandler) {
    

the interceptor barrel:

import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { LanguageInterceptor } from './lang-interceptor';

export const httpInterceptorProviders = [
  { provide: HTTP_INTERCEPTORS, useClass: LanguageInterceptor, multi: true }
];

the shared module

import { NgModule } from '@angular/core';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { HttpClient, HttpClientModule, HttpClientJsonpModule } from '@angular/common/http';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { httpInterceptorProviders } from 'src/utilities/interceptor-barrel';
import { ShareModule } from '@ngx-share/core';
import { FormsModule, ReactiveFormsModule }   from '@angular/forms';

export function HttpLoaderFactory(http: HttpClient) {
    return new TranslateHttpLoader(http, '../assets/i18n/', '.json');
}

const MODULES = [
    HttpClientModule,
    HttpClientJsonpModule,
    CommonModule,
    RouterModule,
    ShareModule,
    FormsModule,
    ReactiveFormsModule
];

@NgModule({
    imports: [
        MODULES,
        TranslateModule.forRoot({
            defaultLanguage: 'en',
            loader: {
                provide: TranslateLoader,
                useFactory: (HttpLoaderFactory),
                deps: [HttpClient]
            }
        }),
    ],
    exports: [
        MODULES,
        TranslateModule
    ],
    declarations: [],
    providers: [
        httpInterceptorProviders
    ],
})

the lazy loaded module:

 // ....
imports: [
        SharedModule
    ]
 // ....
 providers: [
        LanguageService
    ]

Upvotes: 1

Views: 14971

Answers (4)

user13391764
user13391764

Reputation: 11

That error occur when you have to import your module inside imports but forgot to add in export section. e.g:

@NgModule({
      declarations: [
      ],
      imports: [
        RadioGroupModule,
      ],
      exports: [
        
      ],
    
    })
    export class SharedModule { }

Upvotes: 0

Mohamed Mohsen
Mohamed Mohsen

Reputation: 187

I've faced the same issue, but I've finally found that I should restart the angular app and everything worked fine after the restart.

Upvotes: 0

Poul Kruijt
Poul Kruijt

Reputation: 71911

Your LanguageService should not be added to the providers of the lazy loaded module. It should not be added to any providers array of a module. It should have a providedIn: 'root' in the decorator:

@Injectable({ providedIn: 'root' })
export class LanguageService {}

//  lazy loaded module
imports: [
  SharedModule
]

// ....
providers: []

Interceptors on the other hand, should either be declared in your core module, which is included in the App root once. Or in a lazy loaded module, to define a interceptor just for that lazy loaded module


You should restructure your application. Split up your SharedModule to -only- (!important) include components/pipes/directives. These are things that should go in a SharedModule. What -definitely- should not go in there, are application related services and imports.

By the looks of it, your SharedModule should be a CoreModule, and only be imported (not exported) in your AppModule. You should -not- import this module in a lazy loaded module. In your case it will redeclare the HttpClientModule -without- the interceptors, because they are declared in the root and not in the lazy module, making you have the issues you're facing.

Angular itself has a good overview of what kind of modules there are, and what they should and should not contain, and where they should be or should not be imported:

There are five general categories of feature modules which tend to fall into the following groups:

  • Domain feature modules.
  • Routed feature modules.
  • Routing modules.
  • Service feature modules.
  • Widget feature modules.

Upvotes: 4

Aakash Garg
Aakash Garg

Reputation: 10979

The problem is in where you include your interceptors. Your Interceptors should be part of your app/core module.

Upvotes: 0

Related Questions