0

I want to try to make a comparison in my component by using if(success) displayMessage else redirectToPage in 3 seconds. But, how can I check this *(this.link$.source.value.success) or (this.link$.getValue()) * if it send NULL. I try display in my console browser this.link$, it's display the BehaivorSubject. I try with a method getValue() it's not work. Can you please help me.

Thanks again

Browser console.log

enter image description here

Service.ts

  private objectRes: BehaviorSubject<ResModel>;
  public activationOrResetResponse: Observable<ResModel>

  constructor(
    public _apiService: ApiService,
  ) {
    super(_apiService);

    this.objectRes = new BehaviorSubject(null) as BehaviorSubject<ResModel>;
    this.activationOrResetResponse = this.objectRes.asObservable();
  }

  public activateOrResetAccount(token: string, typeRoute: string): void {
    this._apiService.get(this.type + "/" + typeRoute + "/" + token).subscribe(
      (res) => {
        this.activationOrReset = res;
        this.objectRes.next(this.activationOrReset);
      },
      (error) => {
        this.activationOrReset = error;
        this.objectRes.next(this.activationOrReset);
      }
    );
  }

Component.ts

  public link$: Observable<ResModel>;
  constructor(
    private _authUserService: AuthUserService,
    private _activeRoute: ActivatedRoute,
  ) {}

  ngOnInit(): void {
    this.getActivationPage();
  }

  public getActivationPage(): void {
    this.link$ = this._authUserService.activationOrResetResponse;
    this._authUserService.activateOrResetAccount(
      this._activeRoute.snapshot.params.token,
      "confirmation"
    );
    console.log("link$: ", this.link$.getValue());   // null ???????
  }
Steve Friedl
  • 3,929
  • 1
  • 23
  • 30

2 Answers2

0

value getter is part of BehaviorSubject(), not the corresponding observable. So you need to assign the BehaviorSubject() instead of the observable to use it. Try the following

public getActivationPage(): void {
  this.link$ = this._authUserService.objectRes;  // <-- assign the `BehaviorSubject`
  this._authUserService.activateOrResetAccount(
    this._activeRoute.snapshot.params.token,
    "confirmation"
  );
  console.log("link$: ", this.link$.value);   // `value` instead of `getValue()`
}

And it won't work because the variable is private in the service.

I'd add that this doesn't look very elegant. Now there are two unnecessary copies of the BehaviorSubject. Better way would be to write a getter in the service. The link$ variable looks redundant to me.

Service

private objectRes: BehaviorSubject<ResModel>;
public activationOrResetResponse: Observable<ResModel>

constructor(public _apiService: ApiService) {
  super(_apiService);

  this.objectRes = new BehaviorSubject(null) as BehaviorSubject<ResModel>;
  this.activationOrResetResponse = this.objectRes.asObservable();
}

get activationValue(): ResModel {
  return this.objectRes.value;
}

Component

  public getActivationPage(): void {
    this._authUserService.activateOrResetAccount(
      this._activeRoute.snapshot.params.token,
      "confirmation"
    );
    console.log("link$: ", this._authUserService.activationValue());
  }

Update

The correct way would be do the following

Component

  ngOnit() {
    this.getActivationPage();
    this._authUserService.activationOrResetResponse.subscribe(
      response => { console.log(response); }
    );
  }

  public getActivationPage(): void {
    this._authUserService.activateOrResetAccount(
      this._activeRoute.snapshot.params.token,
      "confirmation"
    );
  }
ruth
  • 29,535
  • 4
  • 30
  • 57
  • I change a variable private by public and change the code, but it's not work again, I have NULL in concole, why? – Valentyn SHCHERBOV Apr 29 '20 at 19:12
  • Because `activateOrResetAccount()` in the service is an asynchronous function. By the time the `console.log()` is processed the value hasn't been pushed to the `BehaviorSubject`. See here to learn more about asynchronous requests: https://stackoverflow.com/a/14220323/6513921. That is reason for using a `BehaviorSubject` in the first place. Use `value` is a undercutting it, and it won't work. – ruth Apr 29 '20 at 19:15
  • Ok, thanks, I see, I try put setTimeout and it's work, I change my service in async await, thank's again :) – Valentyn SHCHERBOV Apr 29 '20 at 19:23
  • `setTimeout()` is also a work around in this context. The correct way would be to subscribe to the observable. – ruth Apr 29 '20 at 19:24
0

I think you getting your initial value and need to skip it till get a response from your server.

public getActivationPage(): void {
  this.link$ = this._authUserService.activationOrResetResponse;
  this._authUserService.activateOrResetAccount(
    this._activeRoute.snapshot.params.token,
    "confirmation"
  );

  this.link$
  .pipe( 
     skipWhile((value) => !value), // skip null values
     take(1) // if you need the value only once
  )
  .subscribe((res) => console.log(res));  // { "sucess": false, "message": "Bad action link!" }
Abdelrhman Arnos
  • 1,404
  • 3
  • 11
  • 22