Home > Software design >  How to combine two object lists into one list by id in rxjs using observables?
How to combine two object lists into one list by id in rxjs using observables?

Time:09-04

I have two service calls that return with an observable list:

service.getAllUsers(): observable<User[]> where User looks like this:

    User {
     id: number,
     username: string,
     ...
    }

and the other service call:

service.getSomeData() : Observable<Data[]>

 Data {
  userId: number,
  userSomeData1,
  userSomeData2,
  ...
}

I want to merge these two lists into one Observable list, based on userId:

Observable<Result[]>

where Result should looks like this:

 Result {
  id,
  username,
  userSomeData1,
  userSomeData2,
  ...
}

What I have done so far:

const result$ = this.userService.getAllUsers()
                .pipe(switchMap(users => {
                   return this.userService.getSomeData()
                    .pipe(map(data => ({users, data})))
                }))

But its not what I want. Please help me, how can I achive this?

CodePudding user response:

This is my solution, make the two api calls, run a map on the array, find the data for the respective user and finally merge using array destructuring!

    const result$ = forkJoin([
        this.userService.getAllUsers(),
        this.userService.getSomeData(),
    ]).pipe(
        map(([users, data]) => {
            return users.map(user => {
                let clonedData = user;
                const foundData = data.find(x => x.userId === user.id);
                if (foundData) {
                    clonedData = { ...clonedData, ...foundData };
                }
                return JSON.parse(JSON.stringify(clonedData));
            });
        })
    );

CodePudding user response:

Your code was very close, you just need to .map() each element in your users array to a new object with the corresponding data item appended:

const result$ = this.userService.getAllUsers().pipe(
    switchMap(users => this.userService.getSomeData().pipe(
        map(data => users.map(
            u => ({...u, ...data.find(d => d.userId === u.id)})
        ))
    })
));
  • Related