Последовательный каскад Наблюдаемые в соответствии с результатом предыдущего ответа и переназначение на новый объект данных

У меня возникают трудности с использованием мощности Observables, т.е. RxJs 6, чтобы правильно pipe, tap, map, mergemap или что-то еще, что я запрашивал HttpClient. Версия ад со всеми различными функциями делает ее не очень простой ...

Итак, мне нужно сначала выполнить вызов REST, а затем, в зависимости от результата, вероятно, выполнить второй вызов REST и сопоставить два потенциально полученных объекта данных в одном новом объекте данных. Функция должна вернуть Observable.

Итак, в настоящее время я решил это с помощью subject, что я могу делать вручную / последовательно то, что мне нужно. Функция возвращает Subject, в данном случае не Observable. Но поскольку вызывающий абонент просто подписывается на эту функцию, она работает. Следует отметить, что две сервисные функции ниже (userService.loadUserDetails() и adminService.getAdminData()) просто возвращают наблюдаемые, которые они получают от HttpClient.

Так может ли кто-нибудь помочь мне перевести этот пример кода ниже в типичный код RxJs 6?

myFunction(): Observable<any> {
   const s = new Subject();
    let obj: any = {};

    this.userService.loadUserDetails().subscribe((userDetails) => {
        obj.user = userDetails;
        if (userDetails.authorities.includes('ADMIN')) {
            this.adminService.getAdminData().subscribe((adminData) => {
                obj.adminData = adminData;
                s.next(obj);
                s.complete();
            });
        } else {
            s.next(obj);
            s.complete();
        }
    });

    return s;
}

person badera    schedule 22.06.2018    source источник


Ответы (2)


Используйте mergeMap для цепочки и условного возврата

Обновление: изменено mergeMap на switchMap. Incase внутренняя наблюдаемая является непрерывным потоком, и когда исходная наблюдаемая испускает, она также отменяет внутреннюю наблюдаемую.

    this.userService.loadUserDetails().pipe(
    switchMap(user=>
      user.authorities.includes('ADMIN')) ?
      this.adminService.getAdminData().map(adminData=>({adminData,user})):
      Observable.of({user}))
      )
    .subscribe();
person Fan Cheung    schedule 22.06.2018
comment
Зачем нужен последний subscribe() ? Что из наблюдаемого можно вернуть? Большое спасибо! - person badera; 22.06.2018
comment
Хорошее решение????, только что протестировано здесь stackblitz.com/edit/observable-count-shgzzs - person Yerkon; 22.06.2018
comment
Напротив, mergeMap позволяет одновременно активировать несколько внутренних подписок. Может быть, switchMap здесь лучше всего подходит? - person Yerkon; 22.06.2018
comment
Я хочу принять ваш ответ. Поэтому, пожалуйста, добавьте еще несколько комментариев и, возможно, измените mergeMap на switchMap и опишите почему. Большое тебе спасибо! - person badera; 22.06.2018
comment
Обновил ответ - person Fan Cheung; 22.06.2018

Вы можете создать своего собственного наблюдателя. import { Observable } from 'rxjs/Observable';

return Observable.create(observer => {
   this.userService.loadUserDetails().subscribe((userDetails) => {
        obj.user = userDetails;
        if (userDetails.authorities.includes('ADMIN')) {
            this.adminService.getAdminData().subscribe((adminData) => {
                obj.adminData = adminData;
                observer.next(obj);
            });
        } else {
            observer.next(obj);
        }
    });
});
person Chatar Singh    schedule 22.06.2018
comment
Спасибо и вам за ответ. Однако я выберу тот, что выше. В любом случае +1 - person badera; 22.06.2018