I'm working on a project for which I have a question. I'm quite new to Angular and still trying to master the Observables, the Services and the interfaces ^^.
I'm working on a feature for an app that would allow the user to see the sidebar as if he was another user (who gave him the right to do so)
So the logic I'm trying to implement, is that after the selection of the profile I'm calling a method to switch the user display
My HTML
<select (change)="switchUser($event)">
This switchUser method is in sidebar-component.ts:
getUser(userMatricule:any)
{
console.log(userMatricule)
this.userData.getUserData(userMatricule).subscribe((response) => {
this.user = response.data
console.log(this.user)
})
}
switchUser(event:any)
{
console.log(event.target.value)
this.userData.setUser(event.target.value)
this.userData.userMatriculeSource.subscribe(x=>this.userId=x)
console.log(this.userId)
this.getUser(this.userId)
**console.log(this.user)**
}
And finally the user.service.ts
getUserData(matricule:string): Observable<any> {
this.apiUrl = this.baseUrl matricule
this.headers = new HttpHeaders().set('Access-Control-Allow-Origin', '*');
return this.http.get(this.apiUrl)
}
But the thing that I don't understand, is that when I run the code everythign works as it is suppose to. But when I console.log the different step I can see that the previous User is still showing on the last console.log of the switchUser() method.
I thought it could be a misunderstanding on my side, but I want to make sure that I don't run an unecessary request when switching User.
Thanks for your help!
CodePudding user response:
You need to understand how asynchronous fetching of data works. Read this canonical post with it's question in full.
One key point you do not know when the data will be assinged outside the subscription. In other words, you need to subscribe to observables where it's response is needed.
You need to use
RxJS
tap
operator to perform side-effects likeconsole.log
s or assigning value to variables likethis.userId = userId
.RxJS
map
operator to transform the emitted data. In your case returning thedata
property from the emitted object.RxJS
switchMap
higher order mapping operator to switch from one observable to another. In your case switching fromuserMatriculeSource
observable togetData()
observable.
import { Observable } from 'rxjs';
import { map, switchMap, tap } from 'rxjs/operators';
getUser(userMatricule:any): Observable<any> {
return this.userData.getUserData(userMatricule).pipe(
map((response: any) => response.data)
);
}
switchUser(event: any) {
this.userData.setUser(event.target.value);
this.userData.userMatriculeSource.pipe(
tap((userId: any) => this.userId = userId),
switchMap((userId: any) => this.userData.getData(userId))
).subscribe({
next: (userId: any) => {
console.log(userId);
},
error: (error: any) => {
// handle errors
}
});
}