In my angular 12 app Im trying to return some api data before any of my other components load (including the app component). I want to place some returned items in local storage that will be able to reference img urls and other style attributes across the app globally.
I have implemented an APP_INITIALZER class and have called one of our endpoints to grab the mentioned style data. Since promises are being depreciated I am trying to return the items with an observable since they are now available to app initializers in v12.
Here is some of my code:
Method calling app loader in module.ts
export function serviceLoader(appLoader: AppLoaderService){
return ()=> appLoader.init();
}
AppLoader Init Method:
init(){
return this.styleService.getStyles()
.subscribe(res=>{
console.log('DATA: ', res);
this.localStorageService.portal = {
color: res.portalPrimaryColour,
primaryImage: res.portalImageUrl,
logo: res.portalLogoUrl
};
console.log('portal: ', localStorage.getItem("portal"));
},
err =>{
this.localStorageService.portal = {
color: 'blue',
primaryImage: 'assets/images/img.png',
logo: 'assets/images/logo.png'
};
});
}
My issue is that I cant figure out an elegant way set local storage values AFTER any data OR an error has come from the backend. The app intializer will not wait for the .subscribe res or err functions to come back before returning to the app (I understand this is a limit of an Observable and have also tried .map).
I can ensure data comes back by merely not subscribing to the getStyles() method and doing some logic inside it like this:
this.styleService.getStyles()
getStyles Method:
getStyles() : Observable<any>{
return this.http.get<any>(this.apiService.baseUrl + 'portal_style', httpOptions)
.pipe(tap((data) =>
{
console.log('DATA: ', data);
this.localStorageService.portal = {
color: data.portalPrimaryColour,
primaryImage: data.portalImageUrl,
logo: data.portalLogoUrl,
};
console.log('portal: ', localStorage.getItem("portal"));
}
}
However, with that way of doing it I am having issues with adding error catching and custom logic to errors (such as adding hardcoded local storage values). Not to mention that the Observable must finish or the app will not bootstrap.
So I guess my question is - based off the above - does anyone know an elegant way of returning an observable to an app initializer and doing custom logic when its back (and do different logic and handle errors when they come back)?
Thanks!
catchErrorRxJs operator? Seems enough to me in combination with yourtapoperator.catchErrorbut this way the observable is kept alive and the error is not returned quick enough. If there is a server error I need to do some custom log and assign some values to be returned to the app immediately before the initializer ends.catchErrorstops the initializer from bootstrapping. That said, if thecatchErrorwas not present on the pipe it would still not bootstrap either, so i removed the ThrowError from the return statement and just added a string and it works.