Search code examples
global-variablesangular6angular-services

Angular 6 - a few components using the same randomised data that's called only once - how to avoid 'undefined'


I'm trying to use the same data in ngOnInit of several components, the problem is, the data are random every time I subscribe to it. I can only subscribe one time in the entire run of the app. That means, if I subscribe twice, it won't have any use because each component will have something else.

I want to subscribe once in a service and to create a global variable. but when you try to use that global variable in all the components (on ngOnInit) it is always undefined.

How can I make the components wait for that same thing that can only be called once in the app?

export class UsersService {

  public allUsers: Array<Object> = []
  public allUsersUrl: string = 'https://glacial-escarpment-40412.herokuapp.com/users/'

  constructor(private http: HttpClient) { 
    this.getAllUsers().subscribe(data => {
        this.allUsers = data;
        console.log(this.allUsers)
    })
  }

    getAllUsers(): Observable<any> {
        return this.http.get<any>(this.allUsersUrl);
    }

    getUser(id: number): Observable<any> {
        return this.http.get<any>(this.allUsersUrl + id);
    }
}

My components:

export class FirstComponent {

  constructor(private usersService: UsersService){}

    ngOnInit() {
        console.log(this.usersService.allUsers) //undefined
    }

export class SecondComponent {

  constructor(private usersService: UsersService){}

    ngOnInit() {
        console.log(this.usersService.allUsers) //undefined
    }

Please help me :)


Solution

  • You have a synchronism problem. This is your scenario

    1- create first component 1.1 - injecting UsersService 1.2 - UsersService request for ASYNC data (execution continues) 2- FirstComponent get and print this.usersService.allUsers (not still populated because of async request) 3- this.usersService.allUsers is still undefined

    You need Subject Something like this:

    UsersService

    export class UsersService {
    
      private _allUsersSource = new Subject<Array<Object>>();
      private _allUsers$ = this._allUsersSource.asObservable();
    
      public allUsersUrl: string = 'https://glacial-escarpment-40412.herokuapp.com/users/'
    
      constructor(private http: HttpClient) { 
        this.getAllUsers();
      }
    
        getAllUsers(): Observable<any> {
            return this.http.get<any>(this.allUsersUrl).subscribe(
                  data => this._allUsersSource.next(data)
                  );
        }
    
        get allUsers$(): Observable<Array<Object>> {
            return this._allUsers$;
        }
    
        // OTHERS
    }
    

    FirstComponent

    export class FirstComponent {
    
      subscription: Subscription;
      allUsers: Array<Object>;
    
      constructor(private usersService: UsersService){}
    
        ngOnInit() {
            this.subscription = this.usersService.allUsers$.subscribe(users => {
                                      this.allUsers = users;
                                      console.log(this.allUsers);
                                });
    
    
        }
    

    Some thing for SecondComponent