1

On Load, I'm calling the function getData() which will read & map the response to Data[] model and returns back the result. But the function returning undefined object though it's value is assigned.

import { HttpClient} from '@angular/common/http';
import {Data} from "../model";

export class Service {  
   constructor(private http: HttpClient) {}

   getData():Data[]{
    var data: Data[];
    this.http.get(url,{ responseType: 'blob'}).subscribe(response => {
      response.text().then(value => {
          data = <Data[]>JSON.parse(value);
          console.log(data);  ----> {Printing the values as expected i.e., Data Array}
       });
    });
    console.log(data);  ----> {Printing Undefined}
    return testData;
   }

   onLoad(){
      var data:Data[] = this.getData();
      console.log(data)  ---------> {Printing Undefined}
   }
}

Data Class :

export class Data{
 id:number;
 name:string;
 value:string;
}
R. Richards
  • 24,603
  • 10
  • 64
  • 64
Lakshmipathi G
  • 149
  • 3
  • 13
  • 1
    Value is defined asynchronously. Any statements that directly depend on the async data should be async as well (should be inside the subscription). More details on async data here: https://stackoverflow.com/a/14220323/6513921 – ruth Jun 05 '20 at 08:55

2 Answers2

2

Http calls are async calls. Subsequent call will get executed and will not wait for the promise to be resolve.

Your dependent code should be written once it resolved.

Shabbir Dhangot
  • 8,954
  • 10
  • 58
  • 80
1

I'll just show what I would like to do, here's a little bit reconstruction for your codes:

import {from, Observable} from 'rxjs';  // <= several imports you might care
import {map, switchMap} from 'rxjs/operators';  // <= several imports you might care

export class Service {  
  constructor(private http: HttpClient) {}

  getData(): Observable<Data[]> {
    return this.http.get(someurl, {responseType: 'blob'})
      .pipe(
        switchMap((blob: Blob) => {
          return from(blob.text());
        }),
        map(text => {
          return JSON.parse(text) as Data[];
        })
      );
  }

  onLoad(): void {
    this.getData().subscribe((data: Data[]) => {
      console.log(data); // <=== this is where you can log data
    });
  }
}

The basic idea is you should return a aync(aka Observable) result for your http request, and pipe the first result(type of Blob) to another Observable(which is built from a promise) of string value, then map it to a Data array at last, in onLoad you should subscribe the async result and check the data in subscription. In a word, you should keep the data flow asynchronously until it is been resolved

Snart
  • 54
  • 6
  • The getData() can be used straight away on your component with the [async pipe](https://angular.io/api/common/AsyncPipe) – Santi Barbat Jun 05 '20 at 09:54