Подтвердить что ты не робот

SwitchMap vs 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)
      ))
    );
}
4b9b3361

Ответ 1

Вы правы; switchMap отменит подписку на Observable, возвращенную ее аргументом project, как только она снова вызовет функцию project, чтобы создать новый Observable.

RxJs невероятно мощный и плотный, но его высокий уровень абстракции иногда может затруднить понимание кода. Позвольте мне немного разоблачить мраморные диаграммы и документы, данные @Andy Hole, и привести их в актуальность. Вы можете найти описание синтаксиса мрамора, очень ценную для лучшего понимания операторов rxjs из их тестов (по крайней мере, я обнаружил, что это отсутствует/недостаточно выделено в официальные документы).

mergeMap

mergeMap

Первая строка на диаграмме - это источник Observable, который испускает (1,3,5) в разное время. Вторая строка на диаграмме представляет собой протопический Observable, возвращаемый функцией project i => ..., переданный оператору .mergeMap().

Когда источник Observable испускает элемент 1, mergeMap() вызывает функцию project с помощью i=10. Возвращаемый Observable будет излучать 10 три раза, каждые 10 кадров (см. ссылка на синтаксис мрамора). То же самое происходит, когда источник Observable испускает элемент 3, а функция project создает Observable, который испускает 30 три раза. Обратите внимание, что результат mergeMap() содержит все три элемента, сгенерированные каждым наблюдаемым, возвращаемым из project.

switchMap

switchMap Это отличается от switchMap(), который отменит подписку на Observable, возвращенную project, как только он снова вызовет ее в новом элементе. Мраморная диаграмма показывает это с отсутствующим третьим элементом 30 в выходном наблюдаемом.

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

Ответ 2

mergeMap

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

Сопоставляет каждое значение с наблюдаемым, затем выравнивает все эти внутренние наблюдаемые с помощью mergeAll.

введите описание изображения здесь

switchMap

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

Сопоставляет каждое значение с наблюдаемым, затем выравнивает все эти внутренние наблюдаемые с помощью переключателя.

введите описание изображения здесь

Источник: ES6 Observables в RxJS

Ответ 3

Вы правы.

Как вы можете видеть, switchMap используется с функцией поиска. Поиск в этом примере запрограммирован на то, чтобы в основном генерировать запрос на поиск, когда пользователь вводит текст в текстовое поле (с дебютом 350 мс или задержкой).

Это означает, что когда пользователь вводит "har", ngrx отправляет поисковый запрос службе. Когда пользователь вводит другую букву "r", предыдущий запрос отменяется (поскольку нас больше не интересует "har", а "harr" ).

Это очень хорошо показано на мраморных диаграммах, представленных в другом ответе. В mergeMap предыдущие Observables не отменены, поэтому "30" и "50" смешиваются вместе. Используя switchMap, испускаются только 5s, потому что 3 отменены.