8

I am building a simple weather app that uses a REST service to display current weather data in any city entered by the user.

The dashboard page should display the current weather in ~5 cities specified by the user.

So my question is - given an array of 5 cities, what is the best way to issue a call to the REST service (via Angular service) for each element in that array.

Here's a code excerpt from my initial attempt:

locations: string[] = ["Seattle", "Woodinville", "Krasnoyarsk", "Stockholm", "Beijing"];

...

ngOnInit() {

    this.locations.forEach(function(element) {
      this.weatherService.getWeather(element).subscribe((data) => {
        console.log(data);
      });
    });

  }

But this yields an error: Failed to compile.

c:/Projects/weather-app/src/app/components/dashboard/dashboard.component.ts (19,12): Property 'weatherService' does not exist on type 'void'.

I realize the 'forEach' is not going to work here - but what's the best practice for doing this in ng 4?

Thanks.

jspru
  • 1,060
  • 1
  • 9
  • 17

2 Answers2

15

This will map locations array in array of Observables, forkJoin will emit value, when all responses are in place

Observable
.forkJoin(this.locations
  .map((element) => this.weatherService.getWeather(element))
.subscribe((data) => console.log(data));
valorkin
  • 1,329
  • 9
  • 20
4

The issue is that using the function keyword instead of an arrow function, you are losing what this means. Inside a function using the function keyword, this refers to the function and not to your component class.

Modify to something like this:

this.locations.forEach(element => {
  this.weatherService.getWeather(element).subscribe((data) => {
    console.log(data);
  });
});

Note: You could also consider using forkJoin to wrap multiple observables.

You can find docs on it here: https://www.learnrxjs.io/operators/combination/forkjoin.html

But the example here may be more helpful: rxjs with multiple forkjoin when doing http requests

UPDATE: See improved docs here:

https://rxjs.dev/api/index/function/forkJoin

DeborahK
  • 57,520
  • 12
  • 104
  • 129
  • Thanks for your answer - yes 'this' was the problem. Will look into using 'forkJoin' as well. – jspru Sep 15 '17 at 22:34
  • can you point out the benifits of `forkJoin` or simply calling method in `forEach`? – Pardeep Jain Dec 09 '19 at 07:16
  • With forEach your code needs to subscribe to each Observable. That means you should also unsubscribe from each observable (which is not possible with the code as shown above.) With the forkJoin, you don't have to subscribe to any of the "inner" observables ... only to the "outer" forkJoin. – DeborahK Dec 09 '19 at 18:09