There is a StartupService whose purpose is to initialize a database instance, which, in turn, should be shared between other services afterwards. I run this service inside the app component and while the database instance is not initialized, my user's watching a preloader instead of child components. It looks as follows:
app.component.ts
async ngOnInit(): Promise<void> {
await this.startupService.initializeDatabase();
this.showPreloader = false;
this.showChildComponents = true;
}
It would be nice if the StartupService could add a new database instance inside the dependency injector at run-time:
startup.service.ts
async initializeDatabase(): Promise<void> {
const database: DataBase = await this.createdatabase();
// this.injector.inject(DataBase, database); <-- how actually to do so?
}
so child components' services could then obtain it in usual way through their constructors:
order.service.ts
@Injectable()
export class OrderService {
constructor(private database: Database) { }
}
How can I achieve it, that is to say, how to add a new server to a dependency injector just at run-time?
I'm aware of several options to get a similar result, but unfortunately I find them inconvenient for my use case:
- To use APP_INITIALIZER. While its corresponding task is not fulfilled, the app initialization wouldn't be completed, so the user wouldn't see the preloader. Moreover, there is no handy, out-of-box, way to inform them about errors took place during initializtion.
- To pass children components' services a promise represents database creation task:
order.service.ts
@Injectable()
export class OrderService {
database: Promise<Database>;
constructor(databaseFactory: DatabaseFactory) {
this.database = database.createDatabase();
}
}
However, from now on all the methods of this service are async functions, which return promises. This may uglify code. In particular, I can't implement a method with such a signature: getOrders(): Observable<Order> { }, it should be rather async getOrders(): Promise<Observable<Order>> { }.