Angular APP_INITIALIZER 运行时循环依赖
Angular APP_INITIALIZER circular dependencies at runtime
我有一个循环依赖(在运行-时间!)问题,我不知道如何解决。
我已经注册了一个 APP_INITIALIZER 加载函数,它加载了一个 config.json 文件。此配置文件包含 NGXLogger
的 LogLevel
。
配置文件通过 angular 的 HttpClient
.
加载
除此之外,我注册了一个HttpInterceptor
,它使用NGXLogger
.
似乎 angular 试图按以下顺序解决所有问题:
APP_INITIALIZER
,所以运行这个函数先
- 初始化器的加载函数触发了一个
http
调用,所以首先运行通过拦截器
- 加载
HttpInterceptor
=> NGXLogger
的依赖项
- 根据
APP_INITIALIZER
中的配置文件为 NGXLogger
配置提供程序 =>
- 抛出错误,配置未定义
如何解决这种循环依赖?有没有办法完全跳过 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();
}
}
假后端拦截器:
@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) { }
并在加载方法中
const httpClient = new HttpClient(this.httpBackend);
httpClient.get<AppConfig>(`/assets/configuration/${environment.configFile}`)
.pipe(
tap((config: any) => {
this.config = config;
})
)
.toPromise();
我有一个循环依赖(在运行-时间!)问题,我不知道如何解决。
我已经注册了一个 APP_INITIALIZER 加载函数,它加载了一个 config.json 文件。此配置文件包含 NGXLogger
的 LogLevel
。
配置文件通过 angular 的 HttpClient
.
除此之外,我注册了一个HttpInterceptor
,它使用NGXLogger
.
似乎 angular 试图按以下顺序解决所有问题:
APP_INITIALIZER
,所以运行这个函数先- 初始化器的加载函数触发了一个
http
调用,所以首先运行通过拦截器 - 加载
HttpInterceptor
=>NGXLogger
的依赖项
- 根据
APP_INITIALIZER
中的配置文件为 - 抛出错误,配置未定义
NGXLogger
配置提供程序 =>
如何解决这种循环依赖?有没有办法完全跳过 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();
}
}
假后端拦截器:
@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) { }
并在加载方法中
const httpClient = new HttpClient(this.httpBackend);
httpClient.get<AppConfig>(`/assets/configuration/${environment.configFile}`)
.pipe(
tap((config: any) => {
this.config = config;
})
)
.toPromise();