Angular App initialization with Observables

2.7k views Asked by At

I have this application which needs some initialization before starting. I'm using the recommended way, with the APP_INITIALIZER, the factory function, etc. along with the syntax in the factory function that allows the use of observables instead of promises.

init.service.ts

...
constructor(private http: HttpClient){}
...
public init(){
  return this.http.get(url).subscribe((data) => {
    // save data in local variables
  });
}
...

app.module.ts

... 
export function initializeApp(initService: InitService) {
  return () => initService.init(); // this should convert the Obs into a Promise before return
}
...
providers: [
  {
    provider: APP_INITIALIZER,
    useFactory: initializeApp,
    deps: [InitService],
    multi; true
  }
]
...

Now, this is not working, meaning that the application starts (components rendering and all) before the initialization is completed.

As far as I understand the problem is that the function init() should return an Observable object. Still, I want the .subscribe() part to be defined inside the service function. Is there any way of subscribing to an Observable and returning the Observable object in the same line? (simply prepending a return as I did, did not work)

I guess this is the only thing missing, as the provider will ensure that the Promise is resolved before starting the App ?

Thanks for any help,

--Thomas

2

There are 2 answers

0
zeroquaranta On

Apparently a trivial solution to my question is

public init(): Observable<any>{
  let obs this.http.get(url);
  obs.subscribe((data) => {
    // save data in local variables
  });
  return obs;
}

Probably not fully compliant with Observables best practices, but so far seems to be working.

3
spots On

The APP_INITIALIZER expects an Observable, so your InitService will need to simply map the response data, instead of subscribing.

  return this.http.get(url).pipe(map(data) => {
    // save data in local variables
  }));

Here's a working example - the APP_INITIALIZER in this example will pre-load a random fact about cats into local storage. The AppComponent can then read the fact out of local storage on init and display it without having to wait.