Angular APP_INITIALIZER 运行时循环依赖

标签 angular circular-dependency

我有一个循环依赖(在运行时!)问题,我不知道如何解决。

我已经注册了一个 APP_INITIALIZER 加载函数,它加载一个 config.json 文件。此配置文件包含 NGXLoggerLogLevel 等。 配置文件是通过Angular的HttpClient加载的。

除此之外,我还注册了一个 HttpInterceptor,它使用 NGXLogger

似乎 Angular 试图按以下顺序解决所有问题:

  1. APP_INITIALIZER,所以先运行这个函数
  2. 初始化程序的加载函数会触发 http 调用,因此首先运行拦截器
  3. 加载HttpInterceptor的依赖项=> NGXLogger
  4. 根据 APP_INITIALIZER 中的配置文件配置 NGXLogger => 的提供程序
  5. 抛出错误,配置未定义

如何解决这种循环依赖?有没有办法完全跳过 APP_INITIALIZER http 调用上的拦截器?

CoreModule.ts:

export function appConfigFactory(configService: AppConfigService) {
  return () => configService.load();
}

export function loggerConfigFactory(configService: AppConfigService): {
  return () => {
    level: (NgxLoggerLevel as any)[configService.config.logLevel] || NgxLoggerLevel.ERROR,
  };
}

@NgModule({
  ...
  providers: [{
    provide: APP_INITIALIZER,
    useFactory: appConfigFactory,
    deps: [AppConfigService],
    multi: true
  }, {
    provide: NgxLoggerConfig,
    useFactory: loggerConfigFactory,
    deps: [AppConfigService]
  }]
})
export class CoreModule {}

AppConfigService.ts:

export class AppConfigService {
  constructor(private http: HttpClient) {}

  load() {
    return this.http
      .get<AppConfig>(`/assets/configuration/${environment.configFile}`)
      .pipe(
        tap((config: any) => {
          this.config = config;
        })
      )
      .toPromise();
  }
}

FakeBackendInterceptor:

@Injectable()
export class FakeBackendInterceptor implements HttpInterceptor {
    constructor(private configService: AppConfigService, private logger: NGXLogger) { }

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        // config is undefined here the first time
        if (!this.configService.config || !this.configService.config.mock === 'true') {
            return next.handle(request);
        }
        this.logger.info('Intercepting request with mock');
        // do things
        ...
        return next.handle(request);
    }
}

最佳答案

您可以使用HttpBackend跳过配置服务中的拦截器

constructor(
    private http: HttpClient,
    private httpBackend: HttpBackend) { }

并在load方法中

const httpClient = new HttpClient(this.httpBackend);
httpClient.get<AppConfig>(`/assets/configuration/${environment.configFile}`)
.pipe(
    tap((config: any) => {
      this.config = config;
    })
  )
  .toPromise();

关于Angular APP_INITIALIZER 运行时循环依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57850927/

相关文章:

javascript - 错误语法错误 : Unexpected token < in JSON at position 0

angular - docker-compose 卡在建筑物上

c++ - 循环依赖 c 意外错误或只是糟糕的设计

javascript - Node.js v.11.6.0 : How to resolve circular dependency?

angular - 默认情况下使用 http 运行时如何使用 https 运行 Angular?

angularjs - Angular 2 到 4 迁移的 package.json 更改

angular - 将 Angular 从任何版本更新到最新的稳定版

c# - 泛型的循环依赖

mysql - 如何避免 MySQL 中的循环触发器依赖

java - 使用 Spring Boot 和 Waffle 配置 Spring Security 时发生循环依赖错误