SwitchMap против MergeMap в примере #ngrx
Ниже приведен код из примера Ngrx: https://github.com/ngrx/example-app/blob/master/src/effects/book.ts Мой вопрос заключается в том, почему в первом @Effect он использует switchMap
в то время как другие используют mergeMap
, Это потому, что первый @Effect имеет дело с сетью, а с switchMap
Вы можете отменить предыдущий сетевой запрос, если он запущен?
@Effect() search$ = this.updates$
.whenAction(BookActions.SEARCH)
.map<string>(toPayload)
.filter(query => query !== '')
.switchMap(query => this.googleBooks.searchBooks(query)
.map(books => this.bookActions.searchComplete(books))
.catch(() => Observable.of(this.bookActions.searchComplete([])))
);
@Effect() clearSearch$ = this.updates$
.whenAction(BookActions.SEARCH)
.map<string>(toPayload)
.filter(query => query === '')
.mapTo(this.bookActions.searchComplete([]));
@Effect() addBookToCollection$ = this.updates$
.whenAction(BookActions.ADD_TO_COLLECTION)
.map<Book>(toPayload)
.mergeMap(book => this.db.insert('books', [ book ])
.mapTo(this.bookActions.addToCollectionSuccess(book))
.catch(() => Observable.of(
this.bookActions.addToCollectionFail(book)
))
);
@Effect() removeBookFromCollection$ = this.updates$
.whenAction(BookActions.REMOVE_FROM_COLLECTION)
.map<Book>(toPayload)
.mergeMap(book => this.db.executeWrite('books', 'delete', [ book.id ])
.mapTo(this.bookActions.removeFromCollectionSuccess(book))
.catch(() => Observable.of(
this.bookActions.removeFromCollectionFail(book)
))
);
}
6 ответов
Ты прав; switchMap
отписаться от Observable
вернулся его project
аргумент, как только он вызвал project
функционировать снова, чтобы произвести новый Observable
,
RxJs невероятно мощный и плотный, но его высокий уровень абстракции иногда может затруднить понимание кода. Позвольте мне немного разоблачить мраморные схемы и документы, данные @Andy Hole, и привести их в соответствие. Вы можете найти мраморную ссылку на синтаксис очень полезной для лучшего понимания операторов rxjs из их тестов (по крайней мере, я обнаружил, что это отсутствует / недостаточно выделено в официальных документах).
mergeMap
Первая строка на диаграмме - это источник Observable, который испускает (1,3,5)
в разное время. Вторая строка на диаграмме является прототипом Observable, возвращаемым project
функция i => ...
перешел к .mergeMap()
оператор.
Когда источник Observable испускает элемент 1
, mergeMap()
вызывает project
функция с i=1
, Возвращенный Observable будет излучать 10
три раза каждые 10 кадров (см. справочник по синтаксису мрамора). То же самое происходит, когда источник Observable испускает элемент 3
и project
Функция создает Observable, который испускает 30
три раза. Обратите внимание, что результат mergeMap()
содержит все три элемента, сгенерированные каждым Observable, возвращаемым из project
,
switchMap
Это отличается от switchMap()
, который будет отписываться от Observable возвращается project
как только он снова вызовет его для нового элемента. Мраморная диаграмма показывает это с отсутствующей третьей 30
пункт в выводе Observable.
В приведенном вами примере это приводит к отмене ожидающего поискового запроса. Это очень хороший, но трудно получить право собственности, которую вы получаете бесплатно, комбинируя switchMap()
с отменяемыми Observables, возвращенными Angular's Http
оказание услуг. Это может избавить вас от многих головных болей, не беспокоясь о правильной обработке всех условий гонки, которые обычно возникают при асинхронном аннулировании.
Его уже ответили и очень подробно, но посмотрите на это, и вы никогда не забудете, что такое switchmap
Вы правы.
Как видите, switchMap используется с функцией поиска. Поле поиска в этом примере запрограммировано на генерацию запроса поиска, когда пользователь вводит текст в текстовое поле (с задержкой или задержкой 350 мс).
Это означает, что когда пользователь вводит 'har', ngrx отправляет поисковый запрос в службу. Когда пользователь вводит другую букву "r", предыдущий запрос отменяется (поскольку нас больше не интересует "har", а "harr").
Это очень хорошо показано на мраморных диаграммах, приведенных в другом ответе. В mergeMap предыдущие Observables не отменяются, и поэтому "30" и "50" смешиваются вместе. При использовании switchMap испускаются только 5, потому что 3 отменяются.
mergeMap
Проецирует каждое исходное значение в Observable, который объединяется в выходной Observable.
Отображает каждое значение в Observable, а затем выравнивает все эти внутренние Observable, используя mergeAll.
switchMap
Проецирует каждое исходное значение в Observable, которое объединяется в выходной Observable, испуская значения только из самых последних прогнозируемых Observable.
Отображает каждое значение в Observable, а затем выравнивает все эти внутренние Observable, используя переключатель.
Источник: ES6 Observables в RxJS
Да, если вас больше не интересует ответ на предыдущий запрос при поступлении нового ввода, switchMap является подходящим оператором, а не mergeMap.
Вы не хотите, чтобы запрос данных сохранения API отменялся. Вот почему вы должны использовать mergeMap. Поисковый запрос может быть отброшен без потери данных, и пользователь может редактировать свой запрос и не интересоваться данными для старого запроса. Следовательно, switchMap.