Reputation: 1649
UPDATE How I managed to do it is below (scroll to my answer or here's the link): https://stackoverflow.com/a/55013081/1729405
I'm trying to build a APIService in Angular 7. I'm using subscribe to push to an array which I can't access through another service.
Here's the api service method:
getResponse(url):Observable<any> {
return this.http.post(url, '', {responseType: 'text'});
}
getAll() {
this.getResponse(this.todayApiUrl).subscribe(
(response) => {
this.data.push(response);
});
return this.data;
}
Here's how I'm trying to call it in the secondary service:
export class AdsHealthService {
today = this.callResponseApiService.getAll();
constructor(private callResponseApiService: CallResponseApiService) { }
getHealthValue(interval, type) {
let obj = this.today;
console.log(obj);
}
}
In the attached image is what I get when I console.log()
the response. It looks like an array but when I try to access the first element, I get an undefined
message. What am I doing wrong??
Upvotes: 3
Views: 11636
Reputation: 71
you can do it like this:
In your app-component:
public getDataFromService() {
this._api.getData(this);
}
public setData(data: any){
this.data=data;
}
In your service.ts:
public getData(obj: appComponentModel){
this.http.get(url).subscribe(res => obj.setData(res));
}
its not exactly in the same format as your question but is easy one to understand by anyone.
Upvotes: 0
Reputation: 1649
In your service you would need the following:
async getResponse(url) {
return await this.http.post(url, '', {responseType: 'text'}).toPromise();
}
async getAll(url) {
return await this.getResponse(url);
}
In another service/component, you can retrieve the promise like below. To ensure that you're getting a promise back, you'd need to use a try catch block.
async getToday() {
try {
let today = await this.yourServiceName.getAll(this.todayApiUrl);
return today;
} catch(e) {
console.log(e);
}
}
then call:
let data = this.yourServiceName.getToday();
this.data.then((res) => {
// do stuff with 'res' here.
}
There isn't a way to save the value outside a then scope. To avoid hitting the API multiple times, I set up a cache service so that you can store/retrieve from cache when necessary. Here's the link to the article that I referenced for caching: https://hackernoon.com/angular-simple-in-memory-cache-service-on-the-ui-with-rxjs-77f167387e39
Here's what you can do:
if (!this.cacheService.has('some key')) {
let data = this.yourServiceName.init();
this.cacheService.set('some key', data)
} else {
let cache = this.cacheService.get('data');
// do stuff here.
}
Hope that helps!
Upvotes: 1
Reputation: 2537
This happens because the http.post
is asynchronous, you can make it synchronous by making the getResponse()
async
, transforming the Observable
to Promise
by .toPromise()
and adding await
before the http.post
since that the getResponse()
will not return Observable but raw data so the .subscribe()
is no more necessary.
async getResponse(url) {
return await this.http.post(url, '', {responseType: 'text'}).toPromise();
}
async getAll() {
this.data = await this.getResponse('some url');
return this.data
}
async some() {
const data = await this.getAll();
console.log(data);
console.log(this.data);
}
Upvotes: 5
Reputation: 21688
You are not getting data or data as null or undefined because your rest endpoint will return data in the future but your return statement is returned immediately.
Below are the ways you can solve this
async
pipe in template and .map
in the servicemap
below are code
// one method is fine to return data from rest endpoint
getAll(url):Observable<any> {
return this.http.post(url, '', {responseType: 'text'});
}
In you component class
export class AdsHealthService {
constructor(private callResponseApiService: CallResponseApiService) {
this.callResponseApiService.getAll().subscribe( (today) => {
let obj = today;
console.log(obj);
});
}
rawdata = this.callResponseApiService.getAll();
}
Incase you directly show the data in template you can do that using async
pipe.
<div>{{rawdata | async}}</div>
Upvotes: 0