1

In Angular 6, I want to get JSON data (an array of objects) from http://jsonplaceholder.typicode.com/todos and store them to a tempArray. I have done in an arrow function, but after arrow function, tempArray is undefined.

For example, when I want to print the first element of tempArray via console.log(), the result is undefined. How should I do this?

My code is:

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';

interface DataResponse {
  userId: number;
  id: number;
  title: string;
  completed: boolean;
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  constructor( private http: HttpClient ) {}

  ngOnInit(): void { 

    var tempArray: DataResponse[] = [];
    this.http.get('http://jsonplaceholder.typicode.com/todos').subscribe(data => {
      for (var i=0; i<10; i++)  
        tempArray.push(<DataResponse>data[i]);     
    });
    console.log( tempArray[0] );
  }
}
Narendra Jadhav
  • 10,052
  • 15
  • 33
  • 44
Iman
  • 31
  • 1
  • 1
  • 4
  • 3
    first, you need the http stuff in a service, not the component. second, the console.log will fire before the subscribe finishes – mast3rd3mon Aug 16 '18 at 08:36
  • 1
    What does 'http://jsonplaceholder.typicode.com/todos' return ? – Arash Aug 16 '18 at 08:36
  • 1
    Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Muhammed Ozdogan Aug 16 '18 at 08:37

2 Answers2

1

I finally found the solution. The subscribe function has 3 parameters, second and third are optional. The second parameter is when an error occurs and the third parameter is when the all of data is received and at this time we can print the tempArray:

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';

interface DataResponse {
  userId: number;
  id: number;
  title: string;
  completed: boolean;
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  constructor( private http: HttpClient ) {}

  ngOnInit(): void { 

    var tempArray: DataResponse[] = [];
    this.http.get('http://jsonplaceholder.typicode.com/todos').subscribe(
      data => {
                for (var i=0; i<10; i++)  
                  tempArray.push(<DataResponse>data[i]);     
              },
      error=> { 
                console.log("Error in recieving data"); 
              },
      ()   => {
                console.log( tempArray[0] );
              }
    );
  }
}
Iman
  • 31
  • 1
  • 1
  • 4
-1

javascript is asycnc. After you request to the server you are intermediately writing your array first element to console so even response is not recived to you.

So try this:

  var tempArray: DataResponse[] = [];
    this.http.get('http://jsonplaceholder.typicode.com/todos').subscribe((data: DataResponse[]) => {
      /// tempArray = data.slice(); If you want to clone recived data.
    tempArray = data
    console.log( tempArray[0] );
    });

Check this out: How do I return the response from an asynchronous call?

Muhammed Ozdogan
  • 5,341
  • 8
  • 32
  • 53
  • `data.slice()` wont work as `Data` is of type `Object` not `DataResponse`/`DataResponse[]` – mast3rd3mon Aug 16 '18 at 08:44
  • Actually no need to `.slice()`, ` tempArray = data` is okay. – Muhammed Ozdogan Aug 16 '18 at 08:50
  • Also the matter is not `.slice()` , the matter is async programing. – Muhammed Ozdogan Aug 16 '18 at 08:53
  • Thanks for your feed back. I am trying to help people. Actually down voting wasn't necessary you could have edit the answer, if you want to help people too. – Muhammed Ozdogan Aug 16 '18 at 08:56
  • whoever downvoted clearly thought the same as me, that you cant slice an object and you hadnt done type conversion. this answer also isnt the best in terms of best practice – mast3rd3mon Aug 16 '18 at 09:02
  • Thanks to @Muhammed Ozdogan . I understood, what the reason of undefined array is. For example via setTimeout(() => {console.log( tempArray[0] );}, 5000 ); works very good. Because data have been recieved certainly after 5 seconds. But can you say, what is the best method to get and store data? – Iman Aug 16 '18 at 09:05
  • the best way would be have a variable within the injectable service you need yo make for the http call – mast3rd3mon Aug 16 '18 at 09:08
  • No problem, @Iman I am highly recommend this free course :https://www.udacity.com/course/javascript-promises--ud898 by Google and Udacity. And you can read about observable: http://reactivex.io/documentation/observable.html I don't know the best way, but you can try to extract server communication in a separate file like DataResponse.service.ts and try to return promise or observable from your service methods and receive promises or observable s in your component file then you can subscribe them in your component in order to update ui. At least now I am doing this in my apps. – Muhammed Ozdogan Aug 16 '18 at 09:19