简体   繁体   中英

How to make sure setter is done before using getter in Angular 8

Whenever I call my getter I am being returned an undefined value. I have a setter in one of my services, and I am wanting to set a variable then when I use a getter function I want return that variable. I believe the problem is that my setter is running asynchronously so it is not setting my variable before I need to use the getter. I am confused on how to make sure my setter is done before I do anything else. I feel like I need to use a promise but am confused on how to do so. Maybe I am just doing this wrong all together.

// team-member.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

const TEAM_API_URL = 'http://127.0.0.1:8080/api/team';

@Injectable({
  providedIn: 'root'
})

export class TeamMemberService {
  memberPermissions: any; // Variable that is returned as undefined.

  constructor(private http: HttpClient) {
    this.setTeamMemberPermissions = JSON.parse(localStorage.getItem('jwt')).user['username'];
    console.log(this.getTeamMemberPermissions); // Only logging for testing purposes. Getter will be used in my components
  } 

  public singleTeamMemberInfo(username: string): Observable<any> {
    return this.http.get<any>(TEAM_API_URL + '/user/list/' + username);
  }

  set setTeamMemberPermissions(username: string) {
    this.singleTeamMemberInfo(username).pipe(map((r => {
      this.memberPermissions = r['results'][0].permission;
    }))));
  }

  get getTeamMemberPermissions() {
    return this.memberPermissions;
  }
}

The problem is that you don't subscribe to the singleTeamMemberInfo observable, so the http request is not made and the code from pipe is never called. You should replace the pipe(map..) with subscribe

If you want to check if the value was correctly set, remove the console.log from constructor and move it to setTeamMemberPermissions setter

Try this code

set setTeamMemberPermissions(username: string) {
  this.singleTeamMemberInfo(username).subscribe(
    r => {
       this.memberPermissions = r['results'][0].permission
       console.log(this.getTeamMemberPermissions)
  });
}

Edit

If you want to wait till the memberPermission is set you should store the memberPermission in a BehaviorSubject

// team-member.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import {BehaviorSubject, Observable} from 'rxjs';
import { map } from 'rxjs/operators';

const TEAM_API_URL = 'http://127.0.0.1:8080/api/team';

@Injectable({
  providedIn: 'root'
})

export class TeamMemberService {

  // Store the member permission in BehaviorSubject
  private memberPermissions = new BehaviorSubject<any>(null); // Variable that is returned as undefined.

  constructor(private http: HttpClient) {
    this.setTeamMemberPermissions();
  }

  public singleTeamMemberInfo(username: string): Observable<any> {
    return this.http.get<any>(TEAM_API_URL + '/user/list/' + username);
  }

  private setTeamMemberPermissions() {
    const username = JSON.parse(localStorage.getItem('jwt')).user['username'];
    this.singleTeamMemberInfo(username).subscribe(
      r => {
        const permissions = r['results'][0].permission;
        this.memberPermissions.next(permissions)
      }
    )
  }

  get teamMemberPermissions$(): Observable<any> {
    return this.memberPermissions.asObservable();
  }
}


// In your component
export class TeamMemberComponent implements OnInit{

  constructor(private teamMemberService: TeamMemberService) {}

  ngOnInit() {
    this.teamMemberService.teamMemberPermissions$
      .subscribe(value => console.log(value))
  }
}

You have to control how the async code works together, setter and getter is not sufficient in this case, you can try BehaviorSubject()

//set up with an initial false value
memberPermissions=new BehaviorSubject(null)

//it'll only emit when there is a truthy value
getMemberPermission=memberPermisssion.pipe(fliter(value=>!!value))

// when you get your permission from http call 
// you just call .next()
this.http.get<any>(TEAM_API_URL + '/user/list/' + username)
.subscribe(p=>memberPermissions.next(p));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM