简体   繁体   中英

Angular getting a concat instead of a sum in observable

Hi i'm pretty new at Observables and trying a do a sum of numbers nested in a object / array in a service to display this information in my HTML.

Here are the elements:

Services:

  getMedalsPerCountry(id: number): Observable<number> {
    return this.getCountry(id).pipe(
      map((country: any) =>
        country.participations.map((y: any) => y.medalsCount)
      ),
      reduce((a: number, b: number) => a + b, 0)
    );
  }

getAllCountries(): Observable<any> {
    return this.http.get<any>('./assets/mock/olympic.json');
  }

  getCountry(id: number): Observable<any> {
    return this.getAllCountries().pipe(
      map((countries: any) =>
        countries.find((country: any) => country.id == id)
      )
    );
  }

Service is getting data out of the object:

{id: 2, country: 'Spain', participations: Array(3)}
country
: 
"Spain"
id
: 
2
participations
: 
Array(3)
0
: 
{id: 1, year: 2012, city: 'Londres', medalsCount: 20, athleteCount: 315}
1
: 
{id: 2, year: 2016, city: 'Rio de Janeiro', medalsCount: 17, athleteCount: 312}
2
: 
{id: 3, year: 2020, city: 'Tokyo', medalsCount: 17, athleteCount: 321}
length
: 
3

Here's what i've got in component:

    this.tot$ = this.olympicService.getMedalsPerCountry(countryId);
    this.tot$.pipe(take(1)).subscribe((x) => console.log(x));

And this is the console output (strings):

020,17,17

This is what i got without the reduce:

(3) [20, 17, 17]
0
: 
20
1
: 
17
2
: 
17
length
: 
3

This is getting me mad: any help is very welcome:)

It happens becouse in your case your pipe works based on countries(not participations). And the reduce after your map operator gets an array of the medalsCount. So you can move the reduce operator to a result of the map and get the needed result

getMedalsPerCountry(id: number): Observable<number> {
    return this.getCountry(id).pipe(
      map((country: any) =>
        country.participations.map((y: any) => y.medalsCount).reduce((a: number, b: number) => a +  b, 0)
      )
    );
}

And the second option, to use switchMap instead of map, it'll return a new observable, which you can use with the reduce into the pipe

getMedalsPerCountry(id: number): Observable<number> {
    return this.getCountry(id).pipe(
    
      switchMap((country: any) =>
        country.participations.map((y: any) => y.medalsCount)
      ),
      reduce((a: number, b: any) => a +  b, 0)
     );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM