RxJs - Проблемы с разрешением наблюдаемого потока - PullRequest
0 голосов
/ 29 сентября 2019

Итак, у меня есть селектор NgRx, который возвращает Observable с массивом контактов.Я хотел бы отобразить этот поток и для каждого массива контактов отобразить каждый отдельный контакт и сделать запрос Http к Github, чтобы получить изображение их профиля и добавить его к объекту Contact.Тем не менее, я не уверен, как это сделать, не заканчивая Observable из массива Observables.

Ниже я попробовал, но это не работает.

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 ]

1 голос
/ 29 сентября 2019

Используйте switchMap, чтобы отобразить ваш массив contacts в 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 }))
    ))
  ))
);
0 голосов
/ 29 сентября 2019
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 в конвейерный поток.

0 голосов
/ 29 сентября 2019

Проблема здесь в том, что вы используете Array.map, который возвращает Observable для каждого contact.Если вы хотите, чтобы 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 для улучшения производительности.

...