我在注入由异步工厂提供程序创建的依赖项时遇到问题。
我有以下配置:
应用程序模块:
@NgModule({
declarations: [
...
...,
imports: [
BrowserModule,
BrowserAnimationsModule,
FormsModule,
HttpModule,
HttpClientModule,
...
UsersModule.forRoot(),
...
APP_ROUTERS
]
})
export class AppModule {}
APP_ROUTERS :
const rootRouters = [
{path: '', redirectTo: 'tests', pathMatch: 'full'},
{
path: 'users/login',
component: SUserLoginComponent,
resolve: {
localUsers: UsersLocalResolver
},
},
{
path: '',
loadChildren: 'app/test/test.module#TestModule',
canActivate: [SecurityAuthenticationGuard],
data: {
preload: true
}
},
];
export const APP_ROUTERS: ModuleWithProviders = RouterModule.forRoot(rootRouters, {onSameUrlNavigation: 'reload'});
user.modules :
@NgModule({
imports: [
CommonModule,
...
],
declarations: [
SUserLoginComponent,
],
exports: [
SUserLoginComponent
]
})
export class UsersModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: UsersModule,
providers: [
UsersLocalResolver,
{
provide: UsersLocalDbServices,
useFactory: (dbservice: IndexedDBService): Promise<UsersLocalDbServices> => {
console.log('Factory UsersLocalDbServices');
return new Promise<UsersLocalDbServices>(async (resolve) => {
if (dbservice.getVersion() === null) {
await dbservice.open(LOCAL_DATABASE_NAME);
}
const instance = new UsersLocalDbServices(dbservice);
const result = await instance.setup();
resolve(instance);
});
},
deps: [IndexedDBService]
}
]
};
}
}
使用异步工厂的服务(UsersLocalDbServices)被注入到 SUserLoginComponent 组件中,但是在实例化该组件之后将对其进行解析。 如何做到这一点,以便实例在创建组件时就存在?
export class SUserLoginComponent implements OnInit, AfterViewInit {
constructor(private router: Router,
private activatedRoute: ActivatedRoute,
private db: IndexedDBService,
private securityServices: SecurityServices,
private usersLocalDbService: UsersLocalDbServices) {
}
}
问题在于“ usersLocalDbService”是一个承诺,而不是服务实例。
我已经通过执行以下操作解决了这个问题,但事实是它太可怕了:
async ngOnInit() {
this.usersLocalDbService = await this.usersLocalDbService;
}
是否有任何方法可以注入由异步工厂实例化的依赖关系,并在创建组件之前解决该依赖关系?
答案 0 :(得分:0)
我所看到的使用异步工厂的示例(例如https://juristr.com/blog/2018/01/ng-app-runtime-config/#runtime-configuration)似乎使用了一个函数,该函数返回的函数返回一个Promise,而不是直接返回一个Promise。
将其应用于您的模块会得到:
export class UsersModule {
static forRoot(): ModuleWithProviders {
return {
ngModule: UsersModule,
providers: [
UsersLocalResolver,
{
provide: UsersLocalDbServices,
useFactory: (dbservice: IndexedDBService) => {
return () => {
console.log('Factory UsersLocalDbServices');
return new Promise<UsersLocalDbServices>(async (resolve) => {
if (dbservice.getVersion() === null) {
await dbservice.open(LOCAL_DATABASE_NAME);
}
const instance = new UsersLocalDbServices(dbservice);
const result = await instance.setup();
resolve(instance);
});
}
},
deps: [IndexedDBService]
}
]
};
}
}
答案 1 :(得分:0)
为异步DI做出了一些努力,但几年前已放弃。简短的答案是:异步DI是不可能的(使用angular的实现)。参见https://github.com/angular/angular/issues/23279。
Mark Hughes
的答案建议返回Promise工厂。该想法的源头是有关在引导过程中使用APP_INITIALIZER
令牌执行异步操作的。这不是一个普遍的概念。