APP_INITIALIZER undefined results after page reload









up vote
0
down vote

favorite












I have a simple config service that I've wired with APP_INITIALIZER token in my app.shared.module.ts:



 ConfigService,

provide: APP_INITIALIZER,
useFactory: (configService: ConfigService) =>
() => configService.getStuff(),
deps: [ConfigService],
multi: true
,


This executes the subscription (config.service.ts):



settings: any; 

getStuff()
this.getSettings()
.subscribe(data =>
this.settings = data);
);


getSettings(): Observable<ISettings>
return (this.httpClient
.get<ISettings>(this.localbaseUrl)
.pipe(
catchError(this.errorHandlerSerevice.handleError)
)) as any;



Then I inject this service into other services (through their constructors - which I don't like) and everything works fine on the app start:



constructor()
this.settings = this.configService.settings;



Its fine when I go to the home page and refresh the app from there.
The logic is called and data returned.
However when I refresh a particular page that uses the component and calls the constructor it seems to late for the data to arrive back, hence I get undefined returned here:



this.settings = this.configService.settings;


I guess the 'wire up' is wrong...



Any suggestions how to tackle it?










share|improve this question























  • I believe you're following Dave Bush: where to store angular configurations. one caveat he neglects to mention, is the fact that even with this recommendation, you are still obligated to compile per-environment for the sole purpose of changing index.html's <base href> per environment. make sure you're not implementing that for nothing.
    – Stavm
    Nov 9 at 13:34











  • @Stavm Yes, I do compile per environment. Coming back to my original issue - frankly I am annoyed with (1) this implementation and (2) the lack of options I have here and (3) the fact that the Promise makes such a difference here and (4) the fact I cannot rely on the usual page life cycle. It is rather annoying.
    – tom33pr
    Nov 9 at 14:54














up vote
0
down vote

favorite












I have a simple config service that I've wired with APP_INITIALIZER token in my app.shared.module.ts:



 ConfigService,

provide: APP_INITIALIZER,
useFactory: (configService: ConfigService) =>
() => configService.getStuff(),
deps: [ConfigService],
multi: true
,


This executes the subscription (config.service.ts):



settings: any; 

getStuff()
this.getSettings()
.subscribe(data =>
this.settings = data);
);


getSettings(): Observable<ISettings>
return (this.httpClient
.get<ISettings>(this.localbaseUrl)
.pipe(
catchError(this.errorHandlerSerevice.handleError)
)) as any;



Then I inject this service into other services (through their constructors - which I don't like) and everything works fine on the app start:



constructor()
this.settings = this.configService.settings;



Its fine when I go to the home page and refresh the app from there.
The logic is called and data returned.
However when I refresh a particular page that uses the component and calls the constructor it seems to late for the data to arrive back, hence I get undefined returned here:



this.settings = this.configService.settings;


I guess the 'wire up' is wrong...



Any suggestions how to tackle it?










share|improve this question























  • I believe you're following Dave Bush: where to store angular configurations. one caveat he neglects to mention, is the fact that even with this recommendation, you are still obligated to compile per-environment for the sole purpose of changing index.html's <base href> per environment. make sure you're not implementing that for nothing.
    – Stavm
    Nov 9 at 13:34











  • @Stavm Yes, I do compile per environment. Coming back to my original issue - frankly I am annoyed with (1) this implementation and (2) the lack of options I have here and (3) the fact that the Promise makes such a difference here and (4) the fact I cannot rely on the usual page life cycle. It is rather annoying.
    – tom33pr
    Nov 9 at 14:54












up vote
0
down vote

favorite









up vote
0
down vote

favorite











I have a simple config service that I've wired with APP_INITIALIZER token in my app.shared.module.ts:



 ConfigService,

provide: APP_INITIALIZER,
useFactory: (configService: ConfigService) =>
() => configService.getStuff(),
deps: [ConfigService],
multi: true
,


This executes the subscription (config.service.ts):



settings: any; 

getStuff()
this.getSettings()
.subscribe(data =>
this.settings = data);
);


getSettings(): Observable<ISettings>
return (this.httpClient
.get<ISettings>(this.localbaseUrl)
.pipe(
catchError(this.errorHandlerSerevice.handleError)
)) as any;



Then I inject this service into other services (through their constructors - which I don't like) and everything works fine on the app start:



constructor()
this.settings = this.configService.settings;



Its fine when I go to the home page and refresh the app from there.
The logic is called and data returned.
However when I refresh a particular page that uses the component and calls the constructor it seems to late for the data to arrive back, hence I get undefined returned here:



this.settings = this.configService.settings;


I guess the 'wire up' is wrong...



Any suggestions how to tackle it?










share|improve this question















I have a simple config service that I've wired with APP_INITIALIZER token in my app.shared.module.ts:



 ConfigService,

provide: APP_INITIALIZER,
useFactory: (configService: ConfigService) =>
() => configService.getStuff(),
deps: [ConfigService],
multi: true
,


This executes the subscription (config.service.ts):



settings: any; 

getStuff()
this.getSettings()
.subscribe(data =>
this.settings = data);
);


getSettings(): Observable<ISettings>
return (this.httpClient
.get<ISettings>(this.localbaseUrl)
.pipe(
catchError(this.errorHandlerSerevice.handleError)
)) as any;



Then I inject this service into other services (through their constructors - which I don't like) and everything works fine on the app start:



constructor()
this.settings = this.configService.settings;



Its fine when I go to the home page and refresh the app from there.
The logic is called and data returned.
However when I refresh a particular page that uses the component and calls the constructor it seems to late for the data to arrive back, hence I get undefined returned here:



this.settings = this.configService.settings;


I guess the 'wire up' is wrong...



Any suggestions how to tackle it?







angular typescript






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 9 at 13:07









Kirk Larkin

16.8k33452




16.8k33452










asked Nov 9 at 12:42









tom33pr

133112




133112











  • I believe you're following Dave Bush: where to store angular configurations. one caveat he neglects to mention, is the fact that even with this recommendation, you are still obligated to compile per-environment for the sole purpose of changing index.html's <base href> per environment. make sure you're not implementing that for nothing.
    – Stavm
    Nov 9 at 13:34











  • @Stavm Yes, I do compile per environment. Coming back to my original issue - frankly I am annoyed with (1) this implementation and (2) the lack of options I have here and (3) the fact that the Promise makes such a difference here and (4) the fact I cannot rely on the usual page life cycle. It is rather annoying.
    – tom33pr
    Nov 9 at 14:54
















  • I believe you're following Dave Bush: where to store angular configurations. one caveat he neglects to mention, is the fact that even with this recommendation, you are still obligated to compile per-environment for the sole purpose of changing index.html's <base href> per environment. make sure you're not implementing that for nothing.
    – Stavm
    Nov 9 at 13:34











  • @Stavm Yes, I do compile per environment. Coming back to my original issue - frankly I am annoyed with (1) this implementation and (2) the lack of options I have here and (3) the fact that the Promise makes such a difference here and (4) the fact I cannot rely on the usual page life cycle. It is rather annoying.
    – tom33pr
    Nov 9 at 14:54















I believe you're following Dave Bush: where to store angular configurations. one caveat he neglects to mention, is the fact that even with this recommendation, you are still obligated to compile per-environment for the sole purpose of changing index.html's <base href> per environment. make sure you're not implementing that for nothing.
– Stavm
Nov 9 at 13:34





I believe you're following Dave Bush: where to store angular configurations. one caveat he neglects to mention, is the fact that even with this recommendation, you are still obligated to compile per-environment for the sole purpose of changing index.html's <base href> per environment. make sure you're not implementing that for nothing.
– Stavm
Nov 9 at 13:34













@Stavm Yes, I do compile per environment. Coming back to my original issue - frankly I am annoyed with (1) this implementation and (2) the lack of options I have here and (3) the fact that the Promise makes such a difference here and (4) the fact I cannot rely on the usual page life cycle. It is rather annoying.
– tom33pr
Nov 9 at 14:54




@Stavm Yes, I do compile per environment. Coming back to my original issue - frankly I am annoyed with (1) this implementation and (2) the lack of options I have here and (3) the fact that the Promise makes such a difference here and (4) the fact I cannot rely on the usual page life cycle. It is rather annoying.
– tom33pr
Nov 9 at 14:54












1 Answer
1






active

oldest

votes

















up vote
1
down vote



accepted










In order for Angular to wait for your custom APP_INITIALIZER to complete, it expects a Promise to be returned. Your getStuff method isn't returning anything, which means Angular will not wait for this.settings to get set.



You can use toPromise to convert your Observable into a Promise. Here's one example of how this could be done:



getStuff(): Promise<void> 
return this.getSettings()
.toPromise()
.then(data =>
this.settings = data;
);






share|improve this answer




















    Your Answer






    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader:
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    ,
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53225937%2fapp-initializer-undefined-results-after-page-reload%23new-answer', 'question_page');

    );

    Post as a guest






























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    1
    down vote



    accepted










    In order for Angular to wait for your custom APP_INITIALIZER to complete, it expects a Promise to be returned. Your getStuff method isn't returning anything, which means Angular will not wait for this.settings to get set.



    You can use toPromise to convert your Observable into a Promise. Here's one example of how this could be done:



    getStuff(): Promise<void> 
    return this.getSettings()
    .toPromise()
    .then(data =>
    this.settings = data;
    );






    share|improve this answer
























      up vote
      1
      down vote



      accepted










      In order for Angular to wait for your custom APP_INITIALIZER to complete, it expects a Promise to be returned. Your getStuff method isn't returning anything, which means Angular will not wait for this.settings to get set.



      You can use toPromise to convert your Observable into a Promise. Here's one example of how this could be done:



      getStuff(): Promise<void> 
      return this.getSettings()
      .toPromise()
      .then(data =>
      this.settings = data;
      );






      share|improve this answer






















        up vote
        1
        down vote



        accepted







        up vote
        1
        down vote



        accepted






        In order for Angular to wait for your custom APP_INITIALIZER to complete, it expects a Promise to be returned. Your getStuff method isn't returning anything, which means Angular will not wait for this.settings to get set.



        You can use toPromise to convert your Observable into a Promise. Here's one example of how this could be done:



        getStuff(): Promise<void> 
        return this.getSettings()
        .toPromise()
        .then(data =>
        this.settings = data;
        );






        share|improve this answer












        In order for Angular to wait for your custom APP_INITIALIZER to complete, it expects a Promise to be returned. Your getStuff method isn't returning anything, which means Angular will not wait for this.settings to get set.



        You can use toPromise to convert your Observable into a Promise. Here's one example of how this could be done:



        getStuff(): Promise<void> 
        return this.getSettings()
        .toPromise()
        .then(data =>
        this.settings = data;
        );







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 9 at 13:05









        Kirk Larkin

        16.8k33452




        16.8k33452



























             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53225937%2fapp-initializer-undefined-results-after-page-reload%23new-answer', 'question_page');

            );

            Post as a guest














































































            Popular posts from this blog

            Kleinkühnau

            Makov (Slowakei)

            Deutsches Schauspielhaus