How do I return the response from an Observable/http/async call in angular?
Reason:
The reason that it's undefined
is that you are making an asynchronous operation. Meaning it'll take some time to complete the getEventList
method (depending mostly on your network speed).
So lets look at the http call.
this.es.getEventList()
After you actually make ("fire") your http request with subscribe
you will be waiting for the response. While waiting, javascript will execute the lines below this code and if it encounters synchronous assignments/operations it'll execute them immediately.
So after subscribing to the getEventList()
and waiting for the response,
console.log(this.myEvents);
line will be executed immediately. And the value of it is undefined
before the response arrives from the server (or to whatever that you have initialized it in the first place).
It is similar to doing:
ngOnInit(){
setTimeout(()=>{
this.myEvents = response;
}, 5000);
console.log(this.myEvents); //This prints undefined!
}
Solution:
So how do we overcome this problem? We will use the callback function which is the
subscribe
method. Because when the data arrives from the server it'll be inside thesubscribe
with the response.
So changing the code to:
this.es.getEventList()
.subscribe((response)=>{
this.myEvents = response;
console.log(this.myEvents); //<-- not undefined anymore
});
will print the response.. after some time.
What you should do:
There might be lots of things to do with your response other than just logging it; you should do all these operations inside the callback (inside the subscribe
function), when the data arrives.
Another thing to mention is that if you come from a Promise
background, the then
callback corresponds to subscribe
with observables.
What you shouldn't do:
You shouldn't try to change an async operation to a sync operation (not that you can). One of the reasons that we have async operations is to not make the user wait for an operation to complete while they can do other things in that time period. Suppose that one of your async operations takes 3 minutes to complete, if we didn't have the async operations the interface would froze for 3 minutes.
Suggested Reading:
The original credit to this answer goes to: How do I return the response from an asynchronous call?
But with the angular2 release we were introduced to typescript and observables so this answer hopefully covers the basics of handling an asynchronous request with observables.
How do I return function after getting the value in http call?
If you don't want to have to worry about subscriptions you can simply turn into a promise and use async/await
async getFieldsRemote(){
let fields: FormfieldBase<any>[] = [];
const data = await this.http.get('http://localhost:8080/api/getFields').toPromise()
// do what you want with the data
return fields
}
Return a response object from http get in Angular
The reason you dont get any response is that all the HTTP method is async
You have two options to handle the problem
Use the observable provided by angular on itself
let res:ReplaySubject<CommonResponse>=new ReplaySubject();
public getByUserName(username:String):User{
this.http.get<CommonResponse>(BASE_URL+'/'+username)
.subscribe( (response) => { this.res.next(response) },
error => this.errorHandler.handleError(error)
)
}
and then you can use the res REplaySubject to subscribe in your component.
Or if you are not really familiar with RxJs and Observables/ReplaySubject a simpler method is to convert the request to a promise and use await
public async getByUserName(username:String):User{
let res:CommonResponse;
res= await this.http.get<CommonResponse>(BASE_URL+'/'+username).toPromise()
.catch((error)=>{
this.errorHandler.handleError(error)
})
console.log("Response "+ res)
return res.responseObj;
}
wait observable for other observable in it to respond. Angular async
You don't need BehaviorSubject in this kind of scenario.
Something like this should work (I supposed "payload" is the content of your storage ?):
getbyid(id: any): Observable<any> {
return this.http.post<any>(this.serverurl, id));
}
getData(origin: any, id: number): Observable<any> {
if (origin !== 'main page') {
return EMPTY;
}
const payload = this._aes.getItem('localstorage');
return payload ? of(payload) : this.getById(id);
}
If payload
is set, we return an observable with it. If not, an observable with a backend call.
In both cases, you have to subscribe from where you call getData
method and wait response.
Return Observable within Async Function
Need to return an Observable? Start not with not subscribing but piping the Observable and use any of the flattening rxjs operators, for example:
this.http.get(// first request here).pipe(
mergeMap((dataFromFirstRequest) => {
if (dataFromFirstRequest suits requirement for second request) {
return this.http.get(// second http request)
} else {
return of(false); // return a falsy data indicating second request wasn't needed
}
})
)
How to return an observable from http request
You are returning the overservable correctly. The reason why you're getting the error for map is probably because you don't have rxjs
installed
Try this:
npm install rxjs --save
- Add
import { map } from 'rxjs/operators';
to your file
Related Topics
Forcing Web-Site to Show in Landscape Mode Only
How to Save a Base64 Image to User'S Disk Using JavaScript
How to Get the Actual Rendered Font When It's Not Defined in Css
Should CSS Always Precede JavaScript
Webkit-Based Blurry/Distorted Text Post-Animation Via Translate3D
How to Get Number of Rows in ≪Textarea ≫ Using JavaScript
Why the Onclick Element Will Trigger Twice For Label Element
How to Get Nth-Child Selector to Skip Hidden Divs
How to Select Nth Line of Text (Css/Js)
How to Show Popup Message Like in Stack Overflow
Html5 Canvas Camera/Viewport - How to Actually Do It
Is It Possible For Flex Items to Align Tightly to the Items Above Them
Is There a Callback on Completion of a Css3 Animation
Show and Hide Divs At a Specific Time Interval Using Jquery
Get the Device Width in JavaScript
How to Retrieve the Display Property of a Dom Element