RxJs looping over returned array
Asked Answered
C

2

7

Is there a better way using RxJS operators to loop over an array returned from an observable than this to emit a new individual ListingItem?

onGetItemData(){
this.dataService.getItemData().subscribe((itemData) =>
{
  this.itemDataJSON = itemData;
  this.itemDataJSON.forEach(function (value) {
    let new_listing = new ListingItem(value.label,value.market,value.name);
    console.log(new_listing);
  });
 });
}

The API returns a single array containing the items, so I am unable to use .map to access itemData.name

//-- DataService --// 
getItemData(){
 return this.http.get(this._URL, { headers })
        .pipe(map((res: Listings) => res.items))
}
Characteristically answered 27/7, 2018 at 0:26 Comment(1)
flatten might be what you want. this.http.get(this._URL, { headers }) .pipe(flattten(), map(item => item.name))Frasco
W
15

Why don't just pipe a map() ?

this.dataService.getItemData()
    .pipe(
        map(itemData => {
            return itemData.map(value => {
                return new ListingItem(value.label, value.market, value.name);
            })
        })
    )
    .subscribe((listingItem) => {
        console.log(listingItem) // gives an array of listingItem
    });

Note that .map() is a JavaScript's native array function, you will use it to transform the data, by looping over each item of the array

Just for a one-liner:

.pipe(
    map(itemData => itemData.map(value => new ListingItem(value.label, value.market, value.name)))
)
Winfredwinfrey answered 27/7, 2018 at 3:16 Comment(2)
The reason is due to this error on itemData.map: [ts] Property 'map' does not exist on type 'Object' any.... Is that because itemData is an object containing an array?Characteristically
@user4003765 yes. But in your code you are already using .forEach() in your itemData. So is it an object or array? Unless you post a stackblitz that can reproduce the problem, else only you know your code best and we outsiders couldnt be possible try to guess every possibility on where the error is.Winfredwinfrey
P
5

I'm still learning Observables myself, but I think you can create an Observable from an Array like I did in this StackBlitz: https://stackblitz.com/edit/angular-tbtvux

In a nutshell (in Angular 6):

import { from, pipe } from 'rxjs';
...
let observable = from([10, 20, 30])
  .subscribe(v => console.log(v));

So maybe you can pipe the switchMap operator on your observable which returns an array, something like this:

import { switchMap } from 'rxjs/operators';
...
yourArrayObservable$.pipe(
  switchMap(val => from(val))
);

... and then you could use map after that like so:

import { switchMap, map } from 'rxjs/operators';
...
yourArrayObservable$.pipe(
  switchMap(val => from(val)),
  map(val => val * 42)
);

... at least that seems to work in my aforementioned StackBlitz.


Update: I think the flatMap operator also works similarly, with a single operator:

yourArrayObservable$.pipe(
  flatMap(val => val * 42)
);
Preset answered 27/7, 2018 at 1:4 Comment(2)
Error on from(val): [ts] Argument of type 'Object' is not assignable to parameter of type 'ObservableInput<ObservableInput<{}>>'.Characteristically
Fantastic thanks for the switchMap hint. My RXJS fromFetch returned an Observable with an array of all results. But I couldn't seem to pump out an Observable per result. This did it.Metronymic

© 2022 - 2024 — McMap. All rights reserved.