В ответе на RxJS: предотвращение ошибок, связанных с switchMap, Мартин Хохел упомянул классический вариант использования switchMap. Для случая использования, на который он ссылался, switchMap не только действителен; это оптимально. И стоит посмотреть, почему.

Работа с устаревшими результатами

Давайте рассмотрим пример, который включает в себя дорогостоящий вызов серверной службы: поиск адресов, которые соответствуют частичному адресу, введенному в HTML input.

Вот эффект NgRx:

А вот и redux-observable эпопея:

Эффект / эпик устраняет вводимые пользователем данные, так что поиск в бэкэнде не выполняется для каждого нажатия клавиши, и использует distinctUntilChanged, так что поиск не выполняется, если только частичный адрес не изменился. Оператор, который затем используется для сглаживания наблюдаемой серверной части, - switchMap.

Почему?

Из обобщенных рекомендаций в RxJS: Как избежать ошибок, связанных с switchMap, мы знаем, что:

  • concatMap можно использовать как консервативный выбор;
  • mergeMap не следует использовать - важен порядок результатов;
  • switchMap можно использовать - когда выполняется новый поиск, ожидающие результаты больше не нужны; а также
  • exhaustMap не следует использовать - поиск новых частичных адресов не следует игнорировать.

Итак, как бы изменилось поведение, если бы в эффекте / эпике использовался консервативный выбор concatMap, а не switchMap?

Будет ли поведение отличаться, зависит от двух вещей:

  • время, необходимое для выполнения внутреннего поиска; а также
  • время между нажатиями клавиш пользователем.

Оператор debounceTime налагает ограничение на то, как часто может происходить внутренний поиск, поэтому, если выполнение поиска не займет больше времени, чем время устранения неполадок, не будет никакой разницы в поведении между выравниванием с concatMap и с switchMap - независимо от того, насколько медленно пользователь вводит .

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

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

В худшем случае, если используется concatMap, каждое нажатие клавиши приводит к поиску, и результаты этого поиска все равно будут ожидающими при нажатии следующей клавиши, поэтому следующий поиск будет поставлен в очередь. Это приводит к тому, что отображаемые результаты поиска становятся все более несинхронизированными с введенным частичным адресом, и, поскольку каждый из поисков должен быть выполнен до выполнения следующего, может потребоваться некоторое время, чтобы отображаемые результаты стали согласованными с input.

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

TL;DR

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

Этот пост также опубликован в моем личном блоге: ncjamieson.com.