Jody
Jody

Reputation: 1743

How to extract data from RxJS observable

I've been learning Angular recently and am trying to better understand RxJS. Assume I have an API response from HttpClient.get that gives me an Observable of the following JS object:

const response = {
  photos: [
    {
      id: 1,
      src: '1.jpg',
    },
    {
      id: 2,
      src: '2.jpg',
    },
    {
      id: 3,
      src: '3.jpg',
    }
  ]
}

The end result I'm looking for is: ['1.jpg', '2.jpg', '3.jpg']

I am able to do the following to get each individual src one at a time:

const source = from(response.photos);
const images = source.pipe(
    pluck('src')
);
images.subscribe({
    next(x) { 
        console.log(x); // results in: 1.jpg 2.jpg 3.jpg, one item per line.
    }
});

But what I'd like to do, and what I thought would work, is to create an observable of the entire response (as it would be given from Angular's http.get() call) and return all src properties as an array, like this:

const source = of(response);
const images = source.pipe(
    pluck('photos'),  // i expect this to be [{ id: 1, src: '1.jpg' }, ... ]
    map(x => x.src),  // i expect x to to be { id: 1, src: '1.jpg' } (but it is not)
);
images.subscribe({
    next(x) { 
        console.log(x); // i expect x to be the result of the map call earlier, i.e. ['1.jpg', '2.jpg', '3.jpg']
    }
});

I suppose I'm likely getting hung up on expecting the final value vs. the values as they arrive, or something to that effect. If anyone can help explain how to get the desired result or suggest a different/better approach, I'm hoping that something will click and things will start to make more sense.

Upvotes: 0

Views: 3091

Answers (3)

Lasanga Guruge
Lasanga Guruge

Reputation: 874

Here i have substituted your client call with getImages() method In addition to this always follow up the unscubscribing the observables in the ngDestroy method to prevent from memory leaking


let images;
let imageSrc;

getImages(): Observable<any> { 
 return this.httpClient.get(url);
}

this.getImages().pipe().subscribe(response => 
{ 
  this.images = response.photos;
  this.imageSrc = response.map(x => x.src)
});

Upvotes: 0

Yasser Nascimento
Yasser Nascimento

Reputation: 1381

As you need just some data manipulation after get the source's result without any event manipulation, I like to simply use a map like this:

const source = of(response);
const images = source.pipe(map(data => data.photos.map(x => x.src)));
images.subscribe(console.log);

Upvotes: 2

ionut-t
ionut-t

Reputation: 1177

Considering your second approach, there you have an error in the map operator. Basically you are passing an array to the observable and in the map operator the result is expected to be an array and not an object like you are treating it there.

The correct code is the following:

const source = of(response);
    const images = source.pipe(
      pluck("photos"),
      // here map over the output which is an array
      map(x => x.map(y => y.src))
    );
    images.subscribe({
      next(x) {
        console.log(x); // the result is: ['1.jpg', '2.jpg', '3.jpg']
      }
    });

Upvotes: 0

Related Questions