digitalis
digitalis

Reputation: 125

Angular APP_INITIALIZER

I am new to Angular and currently using Angular6 for development purpose. Here is my query. Before my app starts I need to call three services that provide me some configs for the app. Lets call the services as Initialization, Conifg and UserDetails. So I have added the services in the app-module.ts file as below.

`

    export function init_app(initService: InitializationService) {
        return () => initService.getInit();
    }

    export function get_settings(configService: ConfigService) {
        return () => configService.getConfig();
    }
export function get_user_settings(userDetails: UserDetailsService) {
        return () => userDetails.getSettings();
    }

    @NgModule({
      imports: [/*my-imports*/],
      providers: [
        AppLoadService,
        { provide: APP_INITIALIZER, useFactory: init_app, deps: [InitializationService], multi: true },
        { provide: APP_INITIALIZER, useFactory: get_settings, deps: [ConfigService], multi: true },
        { provide: APP_INITIALIZER, useFactory: get_user_settings, deps: [UserDetailsService], multi: true }
      ]
    })

` Now InitializationService has some values that are needed by the other two services to work properly. In app_init the services request are sent immediately.

I need my ConfigService and UserDetailsService to be called only when the call for InitializationService is done.

To tackle this I have done following,

// AppConfig.ts

export class AppConfig {
  public static Config= {};

  public static $subject = new Subject();
}

// InitializationService

getInit () {

const promise = new Promise((resolve, reject) => {
      this.http.get().then(val => {
        AppConfig.config = val;
        AppConfig.$subject.next(val);
      });
};

return promise;
}

//ConfigService

getConfig () {
 if(AppConfig.Config.baseUrl === undefined) {
   AppConfig.$subject.subscribe(val => {
     this.http.get(AppConfig.Config.baseUrl).then(//doSomething);
   })
 }
}

So i create a static subject and subscribe to it. Once the Init service is done, it sends the next value for the subject, which is now subscribed and listened by Config service. Once the subscribe call is received I do my further operation.

Same code is repeated by my UserDetails getSettings() call.

Is my approach correct? Is there any other pattern tried and tested.

Any suggestion or better way to tackle the above?

Thanks in advance.

Regards, hawx

Upvotes: 2

Views: 1865

Answers (2)

smnbbrv
smnbbrv

Reputation: 24561

Use one initialiser and control the whole flow there:

export function initAll(initService: InitializationService, configService: ConfigService, userDetails: UserDetailsService) {
  return () => {
    return initService.getInit().pipe(
      switchMap(() => {
        return flatMap([ConfigService.getConfig(), userDetails.getSettings()]);
      }),
    );
  }
}

Please note that flatMap assumes both operations to be completed; however this is just the approach to go. You have full control to the process over rxjs operators. And, you have only one APP_INITIALIZER

Upvotes: 2

digitalis
digitalis

Reputation: 125

//app-module code

export function initAll(appInitService:AppInitService, configService:ConfigService) {
  // return a promise because thats what the app_init token expects. there is an open ticket with angular related to this. https://github.com/angular/angular/issues/15088
  return () => {
    const promise = new Promise((resolve, reject) => {
      appInitService.load().then(() => {
        configService.fetch().then(() => {
          resolve();
        });
      });
    });
    return promise;
  }
}

//appInitService.load() call

const promise = this.http.get<any>(`myConfigURL`).toPromise();
promise.then(response => {
 Object.assign(AppConfig.ENV, response.value.parameters);
});
return promise;

// config service call

const promise = this.http.get<any>(myConfigUrl).toPromise();
promise.then(response => {
  //do something with response
});
return promise;

I took this approach because it solves my problem of having and maintaining Subject. Plus I was short on time to try and debug of what was going wrong with the Observable stuff.

Thanks for the response though.

Upvotes: 0

Related Questions