1
votes

I'm currently developing an ionic 5 app and I've 2 observables, they returns 2 arrays of different object types. I want to mix some properties of the objects in a single one in a new type of object, but I only want to make the second call to the server if the first one returns values.

Example:

obs1$: Observable<{id: string, name: string, active: boolean}[]>;
obs2$: Observable<{id: string, location: Location, year: date}[]>;

newObs$: Observable<{id: string, name: string, year: date}[]>;

I want:

  1. Call obs1$
  2. If obs1$ returns values then call obs2$, else returns []
  3. When obs2$ returns values, return an array of objects mapping results of both observables
2

2 Answers

0
votes

I've added some interfaces to make the code easier to read. I'm assuming here that your first observable returns an empty array when there is no values. If it returns null instead, you might want to remove .length in the switchMap.

The following code works just fine.

interface First {
  id: string;
  name: string;
  active: boolean;
}
interface Second {
  id: string;
  location: Location;
  year: Date;
}
interface Result {
  id: string;
  name: string;
  year: Date;
}

...
const first$: Observable<First[]>;    // Make sure it's initialized
const second$: Observable<Second[]>;  // Make sure it's initialized
...

const result$: Observable<Result[]> = first$.pipe(
  switchMap(firstArray => !firstArray.length
    ? of([])
    : second$.pipe(
        map(secondArray => firstArray
          .filter(a => secondArray.some(b => a.id === b.id))
          .map(a => ({ first: a, second: secondArray.find(b => a.id === b.id) }))
          .map(values => ({...values.first, year: values.second.year }))
        )
    )
  )
);
0
votes

I guess you are in a class. You can do something like this. But make sure you initialize your observables before mapping it.

  obs1$: Observable<{ id: string; name: string; active: boolean }[]>; 
  obs2$: Observable<{ id: string; location: Location; year: Date }[]>;

  newObs$ = this.obs1$.pipe(
    switchMap((item) => {
      const emptyArray: { id: string; name: string; year: Date }[] = [];
      return item? this.obs2$.pipe(
            map((item2) => {
              const others = item2.map((ent2) => {
                const index = item.findIndex(ent1 => ent1.id === ent2.id)
                let name = ''

                if(index !== -1){
                  name = item[index].name
                }
                const id = ent2.id;
                const year = ent2.year;
                return {name, id, year}
              });

              return others
            }),
          )
        : of(emptyArray);
    }),
  );