2

I am trying to load a configuration file (json) via a service using APP_INITIALIZER in Angular 8. The config contains paths to images and props for thumbnails

app-config.json

    {
  "substitutePictureLink": "../images/not_found.png",
  "noImageFound": "../images/404_not_found.png",
  "thumbnailProps": {
  "width": "400",
    "height": "400",
    "format": "PNG",
    "view": "Interior",
    "withdimensions": "true",
    "withdescription": "true"
  }
}

For loading the config, I created a Service [app-config-service] which looks like this:

app-config-service.ts

export class AppConfigService {

public get appConfig(): any {
    return this._appConfig;
}

public set appConfig(value: any) {
    this._appConfig = value;
}

private _appConfig: any;

constructor(
        private _httpClient: HttpClient,
    ) {
        console.log('constructor app-config-service'); 
        this.loadAppConfig();
    }

public loadAppConfig(): any { 
//also tried a promise here
    return this._httpClient.get('../../../assets/configs/app-config.json')
        .pipe(
            take(1)
        )
        .subscribe(
            (config) => {
                this._appConfig = config;
            }
        );

}

So I need to load the config on startup;

app-module.ts

providers: [
    AppConfigService,
    {
        provide: APP_INITIALIZER,
        multi: true,
        deps: [AppConfigService],
        useFactory: (appConfigService: AppConfigService) => {
            return () => {
                return appConfigService.loadAppConfig();
            };
        }
    }
],
bootstrap: [AppComponent],
})

export class AppModule {
}

When I try to load the configuration, it looks like this:

some-service.ts

    export class someService {

private _noImageFound = this._appConfigService.appConfig.noImageFound;

constructor(
        private _appConfigService: AppConfigService
    ) {
    }

...

public getThumbnail(): Observable<SafeUrl> {
        return this._httpClient.get(this._apiUrl + '/visual-tree/thumbnail?width=400&height=400', {
            responseType: 'blob',
        })
            .pipe(
                map((res: Blob): SafeUrl => this._blobToUrl.transform(res)),
                catchError((err: HttpErrorResponse): Observable<string> => {
                    this._logger.error(ErrorMessage.thumbnailNotLoaded, err);
                    return of(this._noImageFound);
                })
            );
    }
...

The error:

  • Uncaught TypeError: Cannot read property 'noImageFound' of undefined

This error occures directly after loging in. Interesting is also that the constructor of the app-config-service is called two times. My guess is that the there is something weird going on with the references of that service.

1 Answer 1

2

The reason is because Angular waits only for Promises and not Observables. If you convert the loadAppConfig function to return a Promise (though your comment says so that you have tried) it should fix your issue. I have created the scenario you outlined in this stack, Hope this helps!

change below

return this._httpClient.get('../../../assets/configs/app-config.json') 
              .pipe(take(1)) 
              .subscribe((config) => { this._appConfig = config; });

to

return this._httpClient.get('assets/config/config.json')
        .toPromise()
        .then(result => {
         this.appConfig = result;
         return Promise.resolve(result);});}
Sign up to request clarification or add additional context in comments.

2 Comments

Tank you, it somehow works. I did not resolve the promise, this may have been the problem.
according to my knowledge of promises whatever you return from a then callback will be wrapped in a promise, unless it's a promise, so you can just return result instead of returning a new resolved promise

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.