Can I add a service to dependency injector during run-time?

Viewed 40

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>> { }.

0 Answers
Related