RxJs-解决可观察流时遇到问题

时间:2019-09-28 21:03:48

标签: angular rxjs observable

所以我有一个NgRx选择器,该选择器返回带有一个Contacts数组的Observable。我想映射此流,并针对每个联系人数组,映射每个单独的联系人,并向Github发出Http请求以获取其个人资料图片,并将其附加到Contact对象。但是,我不确定如何在不以Observable数组Observable结尾的情况下执行此操作。

下面是我尝试过的方法,但这不起作用。

this.contacts$: Observable<Contact[]> = this.store.select(getContacts).pipe(
  map(contacts => {
    return contacts.map(contact => {
      return this.contactService.getGithub$(contact._id).pipe(
        map(githubInfo => {
          return {
            ...contact,
            imageUrl: githubInfo.avatar_url
          };
        })
      );
    });
  })
);

以下是我收到的错误消息:

Type 'Observable<Observable<Contact>[]>' is not assignable to type 'Observable<Contact[]>'.
  Type 'Observable<Contact>[]' is not assignable to type 'Contact[]'.
    Type 'Observable<Contact>' is missing the following properties from type 'Contact': first_name, last_name, job_title, location, company ts(2322)

任何建议将不胜感激!

3 个答案:

答案 0 :(得分:1)

使用switchMapcontacts数组映射到Observable,该数组同时执行您的http请求并将它们映射到扩展的Contact对象。

this.contacts$: Observable<Contact[]> = this.store.select(getContacts).pipe(
  switchMap(contacts => forkJoin(
    contacts.map(contact => this.contactService.getGithub$(contact._id).pipe(
      map(gitHubInfo => ({ ...contact, imageUrl: githubInfo.avatar_url }))
    ))
  ))
);

答案 1 :(得分:0)

这里的问题是,您正在运行一个Array.map,它为每个contact返回一个Observable。如果您希望Observable返回完整的数组,则需要这样的内容:

this.contacts$: Observable<Contact[]> = this.store.select(getContacts).pipe(
  // take the array and emit each value one by one
  concatMap(contacts => from(contacts)),
  // emit an array containing the contact and the corresponding githubInfo
  concatMap(contact => forkJoin(of(contact), this.contactService.getGithub$(contact._id))),
  // take the returned array and convert it to an Object
  map(([contact, githubInfo]) => ({ ...contact, imageUrl: githubInfo.avatar_url})),
  // concatenate everything into a final Array
  toArray()
);

我必须承认我是在旅途中写的,因此无需测试,但我认为它应该可以工作!

如果保持原始顺序很重要,请保留concatMap。如果不是,请使用mergeMap来提高性能。

答案 2 :(得分:-1)

this.contacts$: Observable<Contact[]> = this.store.select(getContacts).pipe( 
    map(contacts => {
        return contacts.map(contact => {
            return this.contactService.getGithub$(contact._id).pipe(
                map(githubInfo => {
                    return { ...contact, imageUrl: githubInfo.avatar_url };
                })
            );
        });
    }),
    concatAll()
);

只需在管道流中添加concatAll运算符即可。