Angular中的异步工厂提供程序和组件注入



我在注入使用异步工厂提供程序创建的依赖项时遇到问题。

我有以下配置:

应用程序模块:

@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'});

用户模块

@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;
}

是否有任何方法可以注入由异步工厂实例化的依赖项,并在创建组件之前解决该依赖项?

在异步DI方面做了一些努力,但几年前就放弃了。简短的回答是:异步DI是不可能的(使用angular的实现(。看见https://github.com/angular/angular/issues/23279.

Mark Hughes的回答建议归还Promise工厂。这个想法来源于一篇关于在引导过程中使用APP_INITIALIZER令牌执行异步操作的文章。这不是一个普遍的概念。

我看到的使用异步工厂的示例(例如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]
}
]
};
}
}

最新更新