I have service which returns an observable which does an http request to my server and gets the data. I want to use this data but I am getting data as null later after completing pageload in network tab able to see data.
Service
getUserData(userId : string): Observable<any>{
const headers = new Headers({ 'Content-Type': 'application/json' });
return this.http.get<any[]>("user/get", headers)
}
component(userconfigs.ts)
getUserInfo() {
this.service.getUserData(userId).subscribe((response) => {
if (response != null) {
this.myDetails.Name = response[0].name;
this.myDetails.Age = response[1].age;
.
.
return this.myDetails
}
});
}
= ;
We are using getUserInfo()
in multiple components like app component, homepage, footerpage. data is shown as undefined
homepage
ngoninit(){
//calling userconfig.ts getUserInfo() method here to get data
this.userDetails = this._userconfigs.getUserInfo();
}
CodePudding user response:
First, you are trying to use async callbacks (observables) as synchronous.
this.userDetails = this._userConfigs.getUserInfo()
the getUserInfoInfo
does not return anything. it merely calls the service.
this is why userDetails
is null. because the method you are calling doesn't return anything.
secondly, you must wait for the asychronous call to complete
update your getUserInfo to only update the component property once the observable is complete.
getUserInfo() {
this.service.getUserData(userId).subscribe((response) => {
if (response != null) {
this.myDetails.Name = response[0].name;
this.myDetails.Age = response[1].age;
.
.
// Only once the subscription is complete, can you access the data from the observabe.
// so here, you should update your component property
this.userDetails = response;
}
});
}
alternatively, if you want your method to return an observable, you would need to change your code as follows
// return either UserDetail object or undefined if no data returned
getUserInfo(): Observable< UserDetail | undefined > {
// return the observable from the service
return this.service.getUserData(userId).pipe(
map( (response) => {
// gracefully handle no data being returned
if( !response) {
return undefined;
}
// now that we know data exists we can process it.
return {
Name: response[0].name,
age: response[0].age,
.
.
};
})
)
}
then modify your ngoninit
to call this method and wait for the response to process
ngoninit(){
// call method to & udpate component.userDetail upon response
this._userconfigs.getUserInfo().pipe(
// You only need one response as you aren't looking for a stream of data
take(1)
).subcribe( {
next: (response: UserData Undefined) => {
// Only after the observable has completed do you have access to the data.
// so you can now update the component property
// Remembering that this value can be either an object or undefined
this.userDetail = response;
}
});
}
CodePudding user response:
Use BehaviourSubject (https://www.learnrxjs.io/learn-rxjs/subjects/behaviorsubject)
Service
myDetails$ = new BehaviorSubject([]);
getUserInfo(){
this.service.getUserData(userId).subscribe((response)=>{
if(response != null){
this.myDetails$.next(response);
}
});
}
Component
this.service.myDetails$.subscribe((response) => {
this.userDetails.Name = response[0].name;
this.userDetails.Age = response[1].age;
})