Bob Rivers
Bob Rivers

Reputation: 5495

Typescript loop does not work

I'm trying to iterate over an array, but Angular refuses to step in into it...

The array is being filled as follows. As you can see, I'm printing it into the console, and I can see that the array was initialized and filled.

export class CarDetailsComponent implements OnInit, AfterViewInit {
  cars: Array<Car>;

  constructor(private carService: CarService) {}

  ngOnInit() {
      this.cars = this.carService.getCars();
      console.log(this.cars);
  }
}

The array will be consumed into a ngAfterViewInit(). For debug purposes, the first thing that I did was to check if the array is ok. And it is. But, the console.log inside the loop is never called. Why?

ngAfterViewInit() {
  console.log(this.cars);
  for (let i in this.cars) {
    console.log(i);
  }
}

I also tried to for..of, this.cars.slice() and everything seems to be ok...

EDIT (addressing some suggestions in comments)

I added both log suggestions and they show that the array is empty. I've attached a printscreen that shows that console.log(this.cars) shows a valid array, but this.cars.length and JSON.stringify(this.cars) doesn't.

Since I'm noob, I don't know why this behavior occurs. Probably it related with what @Ayman and @Codeepic pointed out.

printscreen

EDIT 2

Regarding @Minko question, I think that it is synchronous. It looks like:

  getCars(): Array<Car> {
    var cars: Car[] = [];
    this.http.get('//localhost:8080/cars).subscribe(data => {
      for (let entry of <Array<any>>data) {
        cars.push(entry);
      }
    });
    return cars;
  }

Upvotes: 0

Views: 1539

Answers (3)

djnose
djnose

Reputation: 945

your method

getCars(): Array<Car> {
    var cars: Car[] = [];
    this.http.get('//localhost:8080/cars).subscribe(data => {
      for (let entry of <Array<any>>data) {
        cars.push(entry);
      }
    });
    return cars;
  }

will very likely always return an empty array. That is because the http request will take a while to get the cars from the server. Also since you can call an asynchronous call in javascript it will not wait until it gets a result and return it.

To wait until your array is filled you can use Promises.

getCars(): Promise<Car[]> {
    return new Promise (allLoadedFromServer => {
      var cars: Car[] = [];
      this.http.get('//localhost:8080/cars).subscribe(data => {
        for (let entry of <Array<any>>data) {
          cars.push(entry);
        }
        allLoadedFromServer(cars);
      });
    }
  }

now you can access the data via:

ngAfterViewInit() {
  this.getCars().then(data=>{
     this.cars = data;
     for (let i of this.cars) {
       console.log(i);
     }
   );
}

that should give you the expected result. Hope it helps

Upvotes: 1

Samuel
Samuel

Reputation: 154

This happens because you are making an http call (your get) and before getting the answer you are trying to use the response object, put your logic inside the subscribe.

Upvotes: 1

codeepic
codeepic

Reputation: 4122

carService.getCars() method is asynchronous. ngAfterViewInit runs after the template was rendered but before the carService.getCars() returns any results. That's why you don't see the console.log in for loop.

Upvotes: 2

Related Questions