Operadores rxjs, como retornar dados aninhados em um único objeto?

Nov 30 2020

Não consigo encontrar uma maneira limpa de buscar dados aninhados da maneira rxjs.

Há um retorno observável de todos os usuários e um retorno observável de todos os posts com um ID de usuário.

getUsers(): Observable<User[]>

e

getPosts(id: string): Observable<[]>

Como eu retornaria uma lista de usuários incluindo suas postagens?

No momento, eu preparo os dados usando 2 assinaturas aninhadas.

nestedFetch() {
  this.service.getUsers()
  .subscribe(
    res => {
      res.forEach((user) => {
        this.service.getPosts(user.Id).subscribe(
          posts => {
            user.posts = posts;
            this.users.push(user);
          },
          err => console.log('something went wrong: ' + err)
        )
      })
    },
    err => console.log('something went wrong: ' + err)
  );
}

Eu prefiro usar operadores assim. Mas como posso retornar usuários, incluindo suas postagens?

nestedFetch() {
  this.service.getUsers().pipe(
    map(users => users.map(u => this.membership.getPosts(u.id))),
    mergeMap(posts => forkJoin(posts))
  ).subscribe(
    res => this.posts = posts, //returns only posts but not users
    err => console.log('something went wrong: ' + err)
  )
}

Respostas

2 MoxxiManagarm Nov 30 2020 at 19:19

Um tubo interno ajuda a estender o usuário por seus posts.

this.service.getUsers().pipe(
  switchMap(users => {
    const postsRequests$ = this.users.map(user => this.service.getPosts(user.id).pipe( // example for a error catch which would lead to an empty array not breaking the forkJoin // catchError(err => of([])), map(posts => ({ ...user, posts })), )); return forkJoin(postsRequests$);
  }),
).subscribe(/* ... */);