无法实例化循环依赖! HTTP_INTERCEPTORS(“ [ERROR->]”):在NgModule CoreModule中

时间:2018-08-02 18:24:40

标签: angular typescript rxjs angular-http-interceptors

我正在使用以下依赖项:

package.json:

{
  "name": "myApp",
  "version": "0.0.0",
  "license": "MIT",
  "scripts": {
    "ng": "ng",
    "start": "ng serve --base-href /myapp/",
    "build": "ng build",
    "build-stage": "ng build --environment=stage --aot --prod --vendor-chunk=false --common-chunk=false",
    "build-prod": "ng build --environment=prod --aot --prod --vendor-chunk=false --common-chunk=false",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^4.2.4",
    "@angular/common": "^4.2.4",
    "@angular/compiler": "^4.2.4",
    "@angular/core": "^4.2.4",
    "@angular/forms": "^4.2.4",
    "@angular/http": "^4.2.4",
    "@angular/platform-browser": "^4.2.4",
    "@angular/platform-browser-dynamic": "^4.2.4",
    "@angular/router": "^4.2.4",
    "@ngx-translate/core": "^7.2.2",
    "@ngx-translate/http-loader": "^1.1.0",
    "bootstrap": "^3.3.7",
    "core-js": "^2.4.1",
    "jquery": "^3.2.1",
    "qrcode": "^1.0.0",
    "rxjs": "^5.4.2",
    "zone.js": "^0.8.14"
  },
  "devDependencies": {
    "@angular/cli": "1.4.2",
    "@angular/compiler-cli": "^4.2.4",
    "@angular/language-service": "^4.2.4",
    "@types/jasmine": "~2.5.53",
    "@types/jasminewd2": "~2.0.2",
    "@types/node": "~6.0.60",
    "codelyzer": "~3.1.1",
    "jasmine-core": "~2.6.2",
    "jasmine-spec-reporter": "~4.1.0",
    "karma": "~1.7.0",
    "karma-chrome-launcher": "~2.1.1",
    "karma-cli": "~1.0.1",
    "karma-coverage-istanbul-reporter": "^1.2.1",
    "karma-jasmine": "~1.1.0",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "~5.1.2",
    "ts-node": "~3.2.0",
    "tslint": "~5.3.2",
    "typescript": "~2.3.3"
  }
}

cross-domain.service.ts:

import { Injectable, NgZone } from '@angular/core';
import { Subject } from 'rxjs/Subject';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

import { environment } from '../../environments/environment';
import { ArticlePreview } from './article.model';

import { TranslateService } from '@ngx-translate/core';

@Injectable()
export class CrossDomainService {
  globalSelectors = new Subject<GlobalSelectors>();
  globalLanguage = new BehaviorSubject<string>('en');
  initialArticlePath: string;
  initialGlobalSelectors: GlobalSelectors;
  private socket;

  constructor(private zone: NgZone,private translateService: TranslateService) {
    translateService.setDefaultLang('en');
  }

  public init() {
    if (this.inIframe) {
      const self = this;
      this.socket = new window['easyXDM'].Socket({
        onMessage(_response) {
          try {
            const response = JSON.parse(_response);
            self.zone.run(() => {
              switch (response.type) {
                case 'tileActionQuery': {
                  if (response.data.action && response.data.action === 'goToArticle') {
                    self.initialArticlePath = response.data.path;
                  }
                  break;
                }
                case 'setGlobalSelectors': {
                  self.initialGlobalSelectors = response.data;
                  self.globalSelectors.next(response.data);
                  break;
                }
                case 'tileInfo': {
                  self.globalLanguage.next(response.data.tileLanguage); 
                  self.translateService.use(response.data.tileLanguage);                
                  break;
                }
              }
            });
          } catch (e) {}
        },
        remote: environment.dashboardSiteUrl
      });
    }
  }          

  private get inIframe () {
    try {
      return window.self !== window.top;
    } catch (e) {
      return true;
    }
  }
}

export interface GlobalSelectors {
  client?: any[];
  jurisdiction?: any[];
  process?: any[];
  year?: any[];
}

app.module.ts:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule, APP_INITIALIZER } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

import { AnalyticsService, CoreModule, CrossDomainService } from './core';
import { TileModule } from './tile/tile.module';


@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    AppRoutingModule,
    TileModule,
    CoreModule
  ],
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: onModuleInit,
      multi: true,
      deps: [CrossDomainService, AnalyticsService]
    }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

export function onModuleInit(crossDomainService: CrossDomainService, analyticsService: AnalyticsService) {
  return () => {
    crossDomainService.init();
    analyticsService.init();
    return new Promise((resolve) => resolve(true));
  };
}

core.module.ts:

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HTTP_INTERCEPTORS, HttpClientModule ,HttpClient } from '@angular/common/http';

import { HttpRequestInterceptor } from './http-request.interceptor';
import { ArticleService } from './article.service';
import { CrossDomainService } from './cross-domain.service';
import { AnalyticsService } from './analytics.service';

import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';

export function translateHttpLoaderFactory(http: HttpClient) {
  return new TranslateHttpLoader(http);
}

@NgModule({
  imports: [
    CommonModule,
    HttpClientModule,
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: translateHttpLoaderFactory,
        deps: [HttpClient]
      }
    })
  ],
  providers: [
    ArticleService,
    CrossDomainService,
    AnalyticsService,
    {
      provide: HTTP_INTERCEPTORS,
      useClass: HttpRequestInterceptor,
      multi: true
    }
  ]
})
export class CoreModule {}

http-request.interceptor.ts:

import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { CrossDomainService } from './cross-domain.service';


@Injectable()
export class HttpRequestInterceptor implements HttpInterceptor {

  language: string = 'en';

  constructor(private crossDomainService: CrossDomainService) {
    crossDomainService.globalLanguage.subscribe((language) => {
      this.language = language;
    });
  }

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const request = req.headers.has('Accept-Language') ?
      req :      
      req.clone({ setHeaders: { 'Accept-Language': this.language } });

    return next.handle(request);
  }
}

在编译项目时出现错误:

ERROR in Error: Provider parse errors:
Cannot instantiate cyclic dependency! HTTP_INTERCEPTORS ("[ERROR ->]"): in NgModule CoreModule in C:/temp/myApp/src/app/core/core.module.ts@-1:-1
    at NgModuleProviderAnalyzer.parse (C:\temp\myApp\node_modules\@angular\compiler\bundles\compiler.umd.js:11699:19)    at NgModuleCompiler.compile (C:\temp\myApp\node_modules\@angular\compiler\bundles\compiler.umd.js:18548:36)
    at AotCompiler._compileModule (C:\temp\myApp\node_modules\@angular\compiler\bundles\compiler.umd.js:24004:32)
    at C:\temp\myApp\node_modules\@angular\compiler\bundles\compiler.umd.js:23916:66    at Array.forEach (<anonymous>)
    at AotCompiler._compileImplFile (C:\temp\myApp\node_modules\@angular\compiler\bundles\compiler.umd.js:23916:19)
    at C:\temp\myApp\node_modules\@angular\compiler\bundles\compiler.umd.js:23829:87
    at Array.map (<anonymous>)
    at AotCompiler.emitAllImpls (C:\temp\myApp\node_modules\@angular\compiler\bundles\compiler.umd.js:23829:52)
    at CodeGenerator.emit (C:\temp\myApp\node_modules\@angular\compiler-cli\src\codegen.js:42:46)
    at C:\temp\myApp\node_modules\@angular\compiler-cli\src\codegen.js:33:61
    at <anonymous>
    at process._tickCallback (internal/process/next_tick.js:188:7)

有人可以帮助我解决此问题吗?

1 个答案:

答案 0 :(得分:2)

尝试不要在构造函数中设置CrossDomainService,而要使用拦截函数

@Injectable()
export class HttpRequestInterceptor implements HttpInterceptor {


  constructor(private injector: Injector) {

  }    
  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
   // try to call the service here.
    language: string = 'en';
    const lanaguageInj= this.injector.get(CrossDomainService);
    const globalLanguage= auth.globalLanguage.subscribe((language) => {
      this.language = language;
    });

    const request = req.headers.has('Accept-Language') ?
      req :      
      req.clone({ setHeaders: { 'Accept-Language': this.language } });

    return next.handle(request);
  }
}