[英]Angular 8 APP_INITIALIZER service start before loading config file
[英]Angular service constructor is being triggered before APP_INITIALIZER can finish
我的應用程序中的根提供的服務和 APP_INITIALIZER 之間似乎存在競爭條件,我不知道如何解決它。
我想確保 APP_INITIALIZER 首先完成,因為被觸發的服務依賴於 APP_INITIALIZER 應該設置的 AppConfig。 由於構造函數首先觸發它使用未定義的值並引發錯誤。
我已經簡化了AppInitService的實現,但是主體是一樣的。 我希望init
返回的 promise 在調用 UserSerialService 構造函數之前解析。 目前構造函數首先被調用並導致錯誤,這意味着init
promise 永遠不會完成。
正在構建的服務
@Injectable({
providedIn: 'root'
})
export class UserSerialService {
public userSerial$: BehaviorSubject<string>;
private _urlPrefix = '/cldflt/user/api/user/my-serial';
constructor(private _configService: AppConfigService,
private _http: HttpClient) {
this.getUserSerial$().pipe(take(1)).subscribe(res => {
this.userSerial$ = new BehaviorSubject<string>(res.body.serial)
})
}
public getUserSerial$ = (): Observable<HttpResponse<Serial>> => {
const url = this._configService.getConfig().baseUrl + `${this._urlPrefix}`;
return this._http.get<any>(url, { observe: 'response' });
}
}
模塊
export function initApp(appInitService: AppInitService) {
console.log("InitApp called");
return () => appInitService.init();
}
@NgModule({
declarations: [
],
imports: [
],
entryComponents: [
],
providers: [
{
provide: APP_INITIALIZER,
useFactory: initApp,
deps: [AppInitService],
multi: true
}
],
bootstrap: [AppComponent]
})
export class AppModule { }
應用初始化服務
@Injectable({
providedIn: 'root'
})
export class AppInitService {
constructor(private _configService: AppConfigService,
private _splitService: SplitIOService) { }
init(): Promise<void>{
console.log("InitApp called");
return Promise.resolve().then(() => {
console.log("Promise complete");
});
}
}
我建議你重構你的代碼以正確的方式處理異步,在這種情況下你不會關心執行順序;
class AppConfigService {
config$ = new ReplaySubject<Configuration>(1);
setConfig(config: Configuration) {this.config$.next(config)}
getConfig(): Observable<Configuration> {return this.config$}
}
class UserSerialService {
// ...
public getUserSerial$ = (): Observable<HttpResponse<Serial>> => {
return this._configService.getConfig().pipe(switchMap(({baseUrl}) =>
this._http.get<any>(url, { observe: 'response' })
);
}
}
您可以在初始化完成后使用 Subject 發出信號並訂閱其他服務並通過 mergeMap 等將兩個可觀察對象鏈接在一起嗎?
您可以稍后注入您的_splitService
,因此稍后將構建它以及它的依賴UserSerialService
export class AppInitService {
constructor(private _configService: AppConfigService,
private injector: Injector) { }
init(): Promise<void>{
console.log("InitApp called");
return Promise.resolve().then(() => {
console.log("Promise complete");
});
}
doSomething() {
const splitService = this.injector.get(SplitIOService);
splitService.youAreNoLongerAProblem();
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.