обновите наблюдаемый метод с помощью if/else, чтобы использовать реактивный стиль

#angular #rxjs

Вопрос:

У меня есть приведенный ниже метод, который я хотел бы обновить до более реактивного стиля. он содержит логику if/else. Я читал, что вы должны иметь возможность разлагаться на потоки, применять фильтр к каждому потоку и объединять потоки обратно, но я не уверен, как применить это к приведенному ниже примеру.

Приведенный ниже пример метода передает флаг исключения. метод сначала вызывает службу http для получения массива. если флаг исключить, если true, то нам нужно вызвать другую службу http, чтобы получить некоторые данные конфигурации, необходимые для фильтрации массива.

Спасибо за вашу помощь.

 method A(boolean excludeSomeCatagory ) : Observable<Species[]> {
  return Observable.create((observer) => {
    getSomeHttpData().subscribe((species: Species[]) => {
      if(!excludeSomeCatagory){
        observer.next(species);
        observer.complete();                                  
      }
      else {
        getSomeConfigDataFromHttp().subscribe(
          (data) => {
          filteredArray: Species[] = applyFilter(data, species);
          observer.next(filteredArray);
          observer.complete();                                                    
        });                                          
      }                             
    });
  }
}             
 

Комментарии:

1. Если каждый раз, когда вы оказываетесь next внутри subscribe а, вы, вероятно, делаете что-то не так. Почти всегда есть способ сделать это с помощью чистых операторов.

Ответ №1:

Что-то вроде этого сработало бы:

 public A(excludeSomeCategory: boolean): Observable<Species[]> {
    return getSomeHttpData().pipe(
        switchMap(species => {
            return !excludeSomeCategory
                ? of(species)
                : getSomeConfigDataFromHttp().pipe(
                    map(data => applyFilter(data, species))
                )
        })
    );
}     
 

Общая идея заключается в том, что вы начинаете свой поток с наблюдаемого из вашего http-вызова, а затем передаете его излучение в нужную вам форму. Вам редко понадобится создавать наблюдаемое использование Observable.create() , потому что rxjs предлагает множество статических операторов, обрабатывающих множество распространенных случаев использования.

Вы также хотите избежать подписок, которые вы не можете легко очистить (вложенные подписки).

Итак, если бы мы просто вернулись getSomeHttpData(); , это было бы типично Observable<Species[]> .

 public A(): Observable<Species[]> {
   return getSomeHttpData();
}
 

Очевидно, что у вас есть еще какая-то логика, которую вы хотите выполнить, чтобы потенциально выполнить дополнительный вызов api, поэтому мы передаем функцию emission ( Species[] ) switchMap , которая будет подписываться на «внутреннюю наблюдаемую» для вас и излучать ее выбросы.

Итак, внутри switchMap вы хотите вернуть наблюдаемое. В вашем случае у вас есть условие, которое может просто вернуть полученное сообщение или выполнить другой http-вызов.

В случае, когда вы хотите испустить предыдущее излучение, мы используем of для создания наблюдаемого значения из простого значения.

В другом случае мы просто возвращаем вызов getSomeConfigDataFromHttp() , который сам по себе возвращает наблюдаемое. Поскольку вы хотите немного преобразовать данные, мы используем map это для обработки.

Комментарии:

1. спасибо, БиззиБоб должен быть признателен

Ответ №2:

Просто верните наблюдаемое напрямую и используйте a SwitchMap .

 method A(boolean excludeSomeCatagory ) : Observable<Species[]> {
    return getSomeHttpData().pipe(
        switchMap((species) => {
            if(!excludeSomeCatagory){
                return of(species)
            } else {
                return getSomeConfigDataFromHttp().pipe(
                    map(data => {
                        return applyFilter(data, species)
                    })
                )
            }
        })
    )
}
 

Комментарии:

1. лол, ты опередил меня на минуту 🙂