Как получить объединенный объект с внутренним наблюдаемым с помощью оператора трубы - PullRequest
0 голосов
/ 05 августа 2020

Я тестирую некоторые из операторов rx js, с которыми я столкнулся в определенных проблемах

У меня есть:

export interface User{
   id: number;
   name: string;
}
export interface PersonalDetail {
   id: number;
   dob: Date;
}
export interface UserDetail {
   id: number;
   name: string;
   dob: Date;
}

this.userService() // return Observable<User[]>
this.userService.getUsersPersonalDataById(id) // return Observable<PersonalDetail>

То, что я делаю так, но он оценивает один по one

this.users: UserDetail[] = [];
this.userService.getAllusers().pipe(
   concatMap((result: User[]) =>
      from(result).pipe(
         concatMap(u => this.userService.getUsersPersonalDataById(u.id).pipe(
              map((p: PersonalDetail) => ({...u, ...p} as UserDetail)))
            )
         )
    )
).subscribe((res: UserDetail) => {
        this.users.push(res);
        console.log(res);
})

Но он оценивает One By One, что мне действительно нужно

this.userService.getAllusers().pipe(
   concatMap((result: User[]) =>
         from(result).pipe(
             concatMap(u => this.userService.getUsersPersonalDataById(u.id).pipe(
                map((p: PersonalDetail) => ({...u, ...p} as UserDetail))
             )
          )
     )
     // some code to return UserDetail[]
   )
).subscribe((res: UserDetail[]) => {
        this.users = res;
        console.log(res);
})

1 Ответ

0 голосов
/ 18 августа 2020

Вот что делает то, что вы хотите.

import {Observable, from, Subscriber} from 'rxjs'
import {mergeMap, map, reduce} from 'rxjs/operators'

type UserDetails = {
  id: number;
  dob: Date
}

type User = {
  id: number,
  name: string
}

const details = [{id: 1, dob: new Date()}, {id: 2, dob: new Date()}, {id: 3, dob: new Date()}]
const users = [{id: 1, name: 'john'}, {id: 2, name: 'bob'}, {id: 3, name: 'alice'}]
const usersObs = from(users)


const findObs = (id: number) => Observable.create((subscriber: Subscriber<UserDetails>) => {
  const result = details.find(obj => obj.id === id);
  subscriber.next(result);
  subscriber.complete();
})

const result = usersObs.pipe(
  mergeMap((user: User) => findObs(user.id)
  .pipe(
    map((details:UserDetails) => {
      return{id: user.id, name: user.name, dob: details.dob}
    }))))
  .pipe(reduce((acc:any[], details) => {
    acc.push(details);
    return acc;
  }, []))

result.subscribe(something => console.log(something)) // this fires once and is an array of user details 
...