Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular subscribe. Can't get to data

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?? enter image description here

like image 747
cbloss793 Avatar asked Jun 10 '26 13:06

cbloss793


2 Answers

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);
  }
like image 198
Josef Katič Avatar answered Jun 12 '26 01:06

Josef Katič


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!

like image 27
cbloss793 Avatar answered Jun 12 '26 01:06

cbloss793