Behavior subject run after startup

hello
i have a problem for getting value from storage or behavior subject before running my app, in my authentication.service.ts i have this :

export class AuthenticationService {
  authenticationState= new BehaviorSubject(false);
  GuestState= new BehaviorSubject(false);
  public WhatsnewState= new BehaviorSubject(false);
  constructor(private storage:Storage,private plt:Platform) {
    this.plt.ready().then(()=>{
      this.checkToken();//this work fine 
    });
    
   }
 checkWhatsNewState(){
    return this.storage.get('whatsNew').then(val =>{
      if(val != null){
        this.WhatsnewState.next(true);
        
      }
    });
  }
isSkipwn(){
    return this.WhatsnewState.value;
  }

and now is my app.component.ts in constructor i can’t get data at starting up my app:

  let welcomeShow:any;
    this.authService.WhatsnewState.subscribe((val)=>{
console.log('log wlcs',val)
;welcomeShow= val;
});
    console.log(' welcome ',welcomeShow);

but i have always welcomeShow false and also in subscribe i have two console.log , once “log wlcs false” and seconde is true, also i try to define welcomeShow before constructor and in subscribe write this.welcomeShow but it not working
thanks for your solution.

Programming reactively has to be an actual commitment; you will just end up frustrated if you treat it as syntactical wankery and assume you’ll still be able to be in charge of what happens when.

It’s also extremely important to give everything proper types: all function parameters and return values, all generics. No any.

Bearing those two things in mind, you need to make a choice here, and there isn’t a “right” answer; tradeoffs are involved whatever way you choose:

A. whatsNew is going to present either true or false. Consumers can rely on it always having a value, but it can change at any time.
B. whatsNew has a third undeterminate state. Consumers must be able to deal with that.
C. whatsNew presents with a second layer of indirection. Consumers can rely on it always having a predictable value, but cannot know when that value will be ready.

Sort of by default, you have implemented option A, but your consumer is apparently not happy with the timing of state changes. To keep going down this path,

private whatsNew$ = new BehaviorSubject<boolean>(false);
watchWhatsNew(): Observable<boolean> { return this.whatsNew$; }

welcomeShow in app.component.ts can be a boolean, but any use of it must be confined to the app component, and you must allow Angular default change detection to handle when it changes. You cannot assign its value anywhere else, because by choosing this design you commit to being OK with it changing at any time, and if you assign it somewhere you break this commitment.

Alternative B still leaves most of the work to consumers, but at least now the type system will work to remind you of the promises you have made:

private whatsNew$ = new BehaviorSubject<boolean | undefined>(undefined);
watchWhatsNew(): Observable<boolean | undefined> { return this.whatsNew$; }

Now you will be made to deal with the undefined case in all consumers. The stale data concerns mentioned earlier still exist, but you will be passing along the undefined possibility as well (unless you cast it away, which defeats the purpose of doing this at all, so don’t do that).

Option C requires the most work in the service:

private whatsNew$ = new BehaviorSubject<boolean>(false);
watchWhatsNew(): Promise<Observable<boolean>> {
  return this.storage.ready()
   .then(() => this.storage.get("whatsNew"))
   .then(wn => this.whatsNew$.next(!!wn))
   .then(() => this.whatsNew$);
}
1 Like

hello
thanks for your reply, but stil not working also let welcomeShow was boolean but not working so problem is not get value is assign this value to local variable because in console.log i see value but i don’t why i can’t save it to local variable.

Which of the three options did you choose to implement? A, B or C? What code did you use to do so? Do you have a minimal reproducible app with proper types on all function parameters, return values, and properties? Can you describe in concrete terms, without using any form of the phrase “not working”, how this code you have behaves differently from how you want it to?

thanks for your reply
three of them work fine(i use c), but when i want to assign resultat to a variable its not work. for example :

     let lien:string;
    //afficher les nouvelles pour premier fois
    this.authService.WhatsnewState.subscribe((val)=>{
      if(!!val){//if result is not true 
        console.log('hier is a false state');
       this.lien="whatsnew";
 }
      });
        this.router.navigate([this.lien]);

and finally variable lien is empty.
also i try this:

   let lien:string;
    //afficher les nouvelles pour premier fois
    this.authService.WhatsnewState.subscribe((val)=>{
      if(val){  // if result is true 
        console.log('hier is a true state');
       this.lien="whatsnew";
 }
      });
        this.router.navigate([this.lien]);

i have log in console but this.lien is still empty.

Really? C involves a second layer of indirection: a Promise<Observable<boolean>>. I don’t see that in your code. In fact in all three options the only way to access an Observable from AuthenticationService is via a function call, yet I don’t see that in your new code either.

Finally,

Sorry, but it feels like I’m not doing a very good job of communicating with you, so somebody else is going to have to take over. Good luck going forward.

in authentication.service.ts i have this methode

 watchWhatsNew():Promise<Observable<boolean>>{
    return this.storage.ready()
    .then(()=>this.storage.get('whatsNew'))
    .then(wn=>this.WhatsnewState.next(!!wn))
    .then(()=>this.WhatsnewState)
  }

which is C , and in constructor i have this for preparing at startup


export class AuthenticationService {
  authenticationState= new BehaviorSubject(false);
  GuestState= new BehaviorSubject<boolean>(false);
  WhatsnewState= new BehaviorSubject<boolean>(false);
  constructor(private storage:Storage,private plt:Platform) {
    this.plt.ready().then(()=>{
      this.checkToken();
      this.checkGuest();
      this.watchWhatsNew();
    });
    
   }

and now in app.component.ts when i want to get data from my BehaviorSubject everything is fine for log in console but not for assigne to local varible:

  let welcomeShow:boolean;
    this.authService.WhatsnewState.subscribe((val)=>{
console.log('log wlcs',val)// log wlcs true
;welcomeShow= val;//here is the problem!!!
});
    console.log(' welcome ',welcomeShow);// welcome false

You ignore what it returns:

Note that there are no publicly-acessible properties in my suggestions for AuthenticationService. This is crucial, because the entire point of this exercise is to give AuthenticationService complete control over the timing and manner of exposing the data. All of the BehaviorSubject properties in AuthenticationService must be private; nobody from outside the class may access them directly, or everything we are trying to do is meaningless.

1 Like

finally i found the solution with ngOnInit and setTimeout() after 25 second it assign exact value from BehaviorSubject to local variable:

ngOnInit(){
  const startupScr="whatsnew";
  this.authService.WhatsnewState.subscribe(val=>this.WelcomeShow=val);
  setTimeout(()=>{
if(!this.WelcomeShow){this.router.navigate([startupScr]);}
  },250)
}

and its works as i wanted.
thank you again.

Sigh.

I guess all I can say at this point is that I hope some future reader gets something out of this conversation.

To that future reader, if they exist:

Obviously, using setTimeout to artificially make your app performance worse and introduce another race condition in order to try to paper over your existing race condition isn’t a good idea.

hi dear
i want to create my first project but when i type this commend in cmd
npm install -g cordova ionic
show me this error

please help me!!! :disappointed_relieved: :disappointed_relieved: :disappointed_relieved: :disappointed_relieved:

i think because you haven’t enough space in your drive so you must make free space to install cordova and ionic