Есть ли более простое и элегантное решение для Observables в каналах RxJS? - PullRequest
2 голосов
/ 09 апреля 2019

Представьте, что у меня есть наблюдаемое, дающее мне шоколадное печенье, но я не хочу есть белые.Но так как я слепой, я должен передать их в службу, чтобы выяснить, является ли данное печенье белым или нет.Но я не сразу получаю ответ.Я предпочел бы получить другое наблюдаемое.

Итак, вот код, который я придумал, но он мне действительно не нравится, и я думаю, что должно быть гораздо более простое и элегантное решение для этого:

// pipe the observable
chocolateCookieObservable$.pipe(
  // use a switchMap to create a new stream containing combineLatest which combines...
  switchMap((chocolateCookie: ChocolateCookie) => combineLatest(
    // an artificially created stream with exactly one cookie...
    of(chocolateCookie),
    // and the answer (also an observable) of my cookie service
    this.chocolateCookieService
      .isChocolateCookieWithWhiteChocolate(chocolateCookie),
    // so I get an observable to an array containing those two things
  )),
  // filtering the resulting observable array by the information contained in 
  // the array (is the cookie white)?
  filter(([chocolateCookie, isWhite]: [ChocolateCookie, boolean]) => !isWhite),
  // mapping the array so that I can throw away the boolean again, ending up 
  // with only the now filtered cookies and nothing more
  map(([chocolateCookie]: [ChocolateCookie, boolean]) => chocolateCookie),
).subscribe((chocolateCookie: ChocolateCookie) => {
  this.eat(chocolateCookie);
}

Хотя это работает и в некоторой степени разумно, это действительно очень запутанно, если вам приходится заключать в капсулу больше этих элементов друг в друге.Разве нет способа напрямую отфильтровать наблюдаемое или отобразить его, чтобы я получал нужную мне информацию, не используя эту странную комбинацию объединить последние?

Ответы [ 2 ]

1 голос
/ 09 апреля 2019

Вы должны разбить это на несколько операторов.

Работая таким образом, вы сможете создавать более читабельный, поддерживаемый код при реализации сложных асинхронных рабочих процессов с Observables.

При рефакторинге ваш код будет выглядеть примерно так:

const isWhite$ = chocolateCookie$.pipe(
    switchMap((chocolateCookie: ChocolateCookie) => this.chocolateCookieService.isChocolateCookieWithWhiteChocolate(chocolateCookie)),
);

chocolateCookie$.pipe(
    withLatestFrom(isWhite$),
    filter(([chocolateCookie, isWhite]: [ChocolateCookie, boolean]) => !isWhite),
    map(([chocolateCookie]: [ChocolateCookie, boolean]) => chocolateCookie),
  ).subscribe((chocolateCookie: ChocolateCookie) => {
    this.eat(chocolateCookie);
  }

Также обратите внимание, что вам на самом деле не нужно добавлять Observable в конец имени переменной, так как вы уже используете $синтаксис для обозначения, что переменная является наблюдаемой.

1 голос
/ 09 апреля 2019

Вы можете использовать filter внутри switchMap, чтобы отфильтровать белые cookie-файлы, а затем отобразить ответ службы обратно в cookie-файл

Вот пример:

chocolateCookieObservable$.pipe(
  switchMap((chocolateCookie: ChocolateCookie) =>
    // async test if its white
    this.chocolateCookieService
      .isChocolateCookieWithWhiteChocolate(chocolateCookie)
      .pipe(
        // filter out white cookies
        filter(isWhite => !isWhite),
        // map back from isWhite to the cookie
        mapTo(chocolateCookie)
      )
  )
).subscribe((chocolateCookie: ChocolateCookie) => {
  // mmm, cookies!!!
  this.eat(chocolateCookie);
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...