Rein Van Leirsberghe
Rein Van Leirsberghe

Reputation: 765

Combine results of nested observables

I am working an a webshop were I want to check if items are already in the cart. I have two observables that needs to do the job:

1: get all the items out of the db

this.itemsService
  .getAll()
  .subscribe(
    items => {
      console.log(items); // [{...},{...},{...},...]
    }
  );

2: if an item is three times in the cart, this function will give me back an observable of an array with three times the item.

public getItemFromCart(itemToGet) {
  return this.cart$.map(cartItems => {
    return cartItems.filter(
      (item: ICartItem) => itemToGet.id === item.idItem
    );
  });
}

What I want to do now is to get all the items, go over each item to check if they are present in the cart using the getItemFromCart and if they are, I need to set the property item.inCart = true. Otherwise it should be false...

I only want to use one subscription and do not want to nest subscriptions...

this.itemsService
  .getAll()
  // do something here to check if the item in the array is present in the cart
  .subscribe(
    items => {
      console.log(items); // [{...},{...},{...},...]
    }
  );

Thanks in advance!

Upvotes: 0

Views: 657

Answers (1)

Jecfish
Jecfish

Reputation: 4189

Since you have both items$ and cart$, you can probably use combineLatest or zip operators, do the following way:

import { of } from 'rxjs/observable/of';
import { zip } from 'rxjs/observable/zip';   
import { combineLatest } from 'rxjs/observable/combineLatest';

// replace with your item service stream
const items$ = of([
  { id: 1, name: 'a' },
  { id: 2, name: 'b' },
  { id: 3, name: 'c' },
  { id: 4, name: 'd' },
  { id: 5, name: 'e' }
]);

// replace with your cart stream
const cart$ = of([
  { id: 1, name: 'a' },
  { id: 2, name: 'b' },
  { id: 3, name: 'c' }
]);

let result = [];
// use zip or combineLatest
combineLatest(items$, cart$)
  .subscribe(([items, cartItem]) => {
    result = items.map(item => ({
      ...item,
      inCart: !!cartItem.find(x => x.id === item.id)
    }));

    // 1, 2, 3 incart = true, 4, 5 incart = false
    console.log(result);
  });

Upvotes: 1

Related Questions