Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to auto run a service from a module when it's imported in Angular?

I wonder how can I run a service from a module when it's imported without any manual service injection and run, just like the RouterModule does.

@NgModule({
  imports: [

    BroserModule,
    MyModuleWithServicesThatShouldAutoRun,

  ]
})
export class AppModule { }
like image 846
Machado Avatar asked Aug 05 '19 15:08

Machado


1 Answers

Disclaimer: this is based on another answer in which was not accepted as the right answer because there was a simpler and easier way to do what the OP needed.

You can use the APP_INITIALIZER injection token to run initialization code before any of your other application code runs.

APP_INITIALIZER is defined in @angular/core and you include it like this:

import { APP_INITIALIZER } from '@angular/core';

APP_INITIALIZER is an OpaqueToken that references the multi provider ApplicationInitStatus service. It supports multiple dependencies and you can use it in your providers list multiple times, e.g.:

@NgModule({
  providers: [
    MyService,
    {
      provide: APP_INITIALIZER,
      useFactory: (service: MyService) => function() { return service.init(); },
      deps: [MyService],
      multi: true
    }]
})
export class AppModule { }

This provider declaration is telling the ApplicationInitStatus class to run the MyService.init() method. init() returns a Promise and ApplicationInitStatus blocks the app startup until the Promise resolves.

export class MyService {

  // omitted other methods for brevity

  init(): Promise<any> {

    // start some observers, do the stuff you need

    // you can even request something via http
    return this.httpClient
      .get('https://someurl.com/example')
      .toPromise()
  }

}

In that way, anything inside init will run and block the application load until the Promise resolves.

Be aware that this can increase the up-front load time for you app by however long the init() method takes. For loading content before openning a route you should use a resolver instead.

Sources:

  • https://stackoverflow.com/a/44731279/4367683 (answer in which this one was based)
  • http://www.learn-angular.fr/how-to-call-an-asynchronous-service-before-bootstrap/
like image 184
Machado Avatar answered Sep 22 '22 23:09

Machado