如何对可观察流中的每个元素进行多个函数调用,以返回“新”对象的可观察流

时间:2020-07-20 19:55:52

标签: angularjs promise rxjs observable

我有一个表达式,它带有可观察的帖子流,并且对于每个帖子,都会评估一个“ posterName”,然后合并回到原始帖子中。

在返回帖子之前,有一种方法可以调用另一个函数来评估第二个属性(当前用户是否喜欢该帖子),然后将其与posterName和原始帖子合并。

请在下面查看代码和注释

this.fService.postList$.pipe( 
      switchMap(_posts => { // switchMap to subscribe to inner

        const getUsers$ = _posts
          .map(post => // array map comments into posterName fetch
      
            this.fService.getUserName(post.uid).pipe(
              // once you have the username, rx map back into the comment with the username assigned
              map(userName => ({...post, posterName: userName.first_name + " " + userName.last_name})),

              catchError((err) => {
                // Handle specific error for this call
                console.log(err)
                return of({...post, posterName: "Anonymous"})
              }),

              first()
            )

            //Where can I write a second function that takes the same posts ID
            //and return a promise that I can "then" so I merge the resolved
            //value in to the post i.e ({...post,posterName: somename , thirdThing: somevalue}) 
        )

    

        return forkJoin(...getUsers$); // forkJoin them all together for parallel execution
      })).subscribe(data => { //doing stuff})

1 个答案:

答案 0 :(得分:1)

这与您要寻找的东西接近吗?

它获取所有帖子,对于每个帖子,它获取用户和所有待办事项。

  • 它首先检索所有帖子。然后将检索到的内容通过管道传输 通过switchMap发布以使结果平坦。

  • 它使用forkJoin合并每个帖子的结果。

  • 它第二次使用forkJoin来组合 发布信息和他们的待办事项(在您的情况下就是他们的喜欢)。

  • 然后将forkJoin的结果映射到一个包含以下内容的结构中:
    帖子,用户名和该用户的待办事项列表。

  • 模板使用异步管道来订阅postData $
    结构并访问所需的结构。

注意:这与您的代码并不完全相同,因为我使用了公共用户/帖子/待办事项API,因此可以确保以下代码可以正常工作。

  // Get all posts
  // Get the user of each post
  // Get the todos for each user
  postData$ = this.http.get<Post[]>(this.postUrl).pipe(
    switchMap(posts =>
      forkJoin(
        posts.map(post =>
          forkJoin([
            this.http.get<User>(`${this.userUrl}/${post.userId}`),
            this.http.get<ToDo[]>(`${this.todoUrl}?userId=${post.userId}`)
          ]).pipe(
            map(([user, todos]) => ({
              post: post,
              userName: user.name,
              todos: todos
            }))
          )
        )
      )
    )
  );


export interface Post {
  userId: number;
  id: number;
  title: string;
  body: string;
}

export interface ToDo {
  userId: number;
  id: number;
  title: string;
  completed: boolean;
}

export interface User {
  id: number;
  name: string;
  username: string;
  email: string;
  website: string;
}

export interface PostData {
  post: Post;
  userName: string;
  toDos: ToDo[];
}

我在这里有个闪电战:https://stackblitz.com/edit/angular-todos-posts-forkjoin-deborahk

相关问题