I have a service UserService
that has a method getUsers()
and this service is shared among different angular components.
The method calls an API and returns the data. I want to hold the result/state of last API call so I used BehaviorSubject
to hold the last state so that if different components call getUsers()
there should be only one API call otherwise hold state must be returned.
This is how I am implementing this
private _users$: BehaviorSubject<User[]>;
constructor(private http: HttpClient) {
this._users$ = new BehaviorSubject([]);
}
getUsers(): BehaviorSubject<User[]> {
if (!this._getUsersState().length) {
this._loadUsers();
this._users$.subscribe(() => {
return this._users$;
});
} else {
return this._users$;
}
}
_loadUsers() {
let _users$ = this.http.get(`${this._context}/users/`);
_users$.subscribe((users: User[]) => {
this._users$.next(Object.assign([], users));
});
}
_getUsersState(): User[] {
return this._users$.getValue();
}
And in the component
this.userService.getUsers().subscribe((users: any) => {
console.log(users);
});
but I am getting the following error
ERROR TypeError: Cannot read property 'subscribe' of undefined
I guess get users returns automatically if the length is 0.
How can I solve this issue? And is this approach good?
Edit your service like this :
private _users$ = new BehaviorSubject<User[]>(null);
public usersChanged = this._users$.asObservable();
constructor(private http: HttpClient) {
}
getUsers(): BehaviorSubject<User[]> {
if (!this._getUsersState().length) {
this._loadUsers();
this._users$.subscribe(() => {
return this._users$;
});
} else {
return this._users$;
}
}
_loadUsers() {
let _users$ = this.http.get(`${this._context}/users/`);
_users$.subscribe((users: User[]) => {
this._users$.next(Object.assign([], users));
});
}
_getUsersState(): User[] {
return this._users$.getValue();
}
edit yout component logic like this:
this.userService.usersChanged
.subscribe((users: any) => {
if(!!users){
console.log(users);
} else {
console.log("No user found!");
}
});
It's a good practise to have a variable that is an observable of your private
behaviorSubject. So you just subscribe to it and whenever its state change, it'll emit.