SwitchMap vs MergeMap dans l'exemple #ngrx

ci-dessous est le code de L'exemple Ngrx:https://github.com/ngrx/example-app/blob/master/src/effects/book.ts ma question est pourquoi dans le premier @Effect, il utilise switchMap alors que les autres utilisent mergeMap. Est-ce parce que le premier @Effet est de traiter avec le réseau, et avec l' switchMap vous pouvez annuler la précédente réseau demande si il fonctionne?

@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)
      ))
    );
}
43
demandé sur Derek Hill 2016-07-21 09:33:35

4 réponses

Vous avez raison; switchMap désabonne de Observable retourné par ses project argument dès qu'il a invoqué l' project fonction à nouveau pour produire un nouveau Observable.

RxJs est incroyablement puissant et dense, mais son haut niveau d'abstraction peut parfois rendre le code difficile à comprendre. Permettez-moi de démonter les diagrammes de marbre et les docs donnés par @Andy Hole un peu et les mettre à jour. Vous pouvez trouver le référence syntaxique de marble très précieux pour mieux comprendre les opérateurs rxjs de leurs tests (au moins j'ai trouvé cela manquant/pas assez souligné dans le documents officiels).

mergeMap

mergeMap

La première ligne du diagramme est la source Observables qui émet (1,3,5) à des moments différents. La deuxième ligne du diagramme est le prototype Observable retourné par le project function i => ... passé à l' .mergeMap() opérateur.

quand la source Observable émet l'élément 1,mergeMap() appelle project function i=1. Le retour de l'Observable émet 10 trois fois, toutes les 10 images (Voir référence syntaxique de marble). Il en va de même lorsque la source Observable émet un élément 3 et project la fonction crée un Observable qui émet 30 trois fois. Notez que le résultat de mergeMap() contient les trois éléments générés par chaque Observable de retour de project.

switchMap

switchMap Ce qui est différent avec switchMap(), qui se désabonne de L'Observable retourné par project dès qu'il a invoqué à nouveau sur un nouvel élément. Le diagramme de marbre indique ceci avec le troisième manquant 30 élément dans la sortie Observable.

dans l'exemple que vous avez donné, cela conduit à l'annulation de la demande de recherche en instance. C'est un très sympa mais dur-à-obtenir-droit propriété, que vous obtenez GRATUITEMENT en combinant switchMap() avec résiliable Observables retourné par Angulaire Http service. Cela peut vous éviter beaucoup de maux de tête sans vous soucier de gérer correctement toutes les conditions de course qui se produisent généralement avec l'annulation async.

64
répondu Johannes Rudolph 2018-02-02 18:28:36

mergeMap

projette chaque valeur source vers un Observable qui est fusionné dans la sortie Observable.

établit une correspondance entre chaque valeur et un Observable, puis aplatit tous ces Observables internes en utilisant mergeAll.

enter image description here

switchMap

projette chaque valeur source vers un Observable qui est fusionné dans la sortie Observable, émettant des valeurs seulement à partir de la plus récente projeté Observables.

établit une correspondance entre chaque valeur et un Observable, puis aplatit tous ces Observables internes en utilisant switch.

enter image description here

Source: ES6 Observables in RxJS

6
répondu Andy Hoyle 2016-07-27 15:58:50

Vous avez raison.

comme vous pouvez le voir, switchMap est utilisé avec la fonctionnalité de recherche. La boîte de recherche dans cet exemple est programmée pour émettre une requête de recherche lorsque l'utilisateur entre du texte dans la boîte de texte (avec un debounce ou un delay de 350ms).

Cela signifie que lorsque l'utilisateur entre 'har', ngrx envoie une demande de recherche pour le service. Lorsque l'utilisateur entre une autre lettre 'r', la requête précédente est annulée (puisque nous ne sommes plus intéressés par 'har', mais "harr").

il est très bien montré dans les diagrammes de marbre fournis dans une autre réponse. Dans mergeMap, les Observables précédents ne sont pas annulés et par conséquent '30' et '50' sont mélangés ensemble. En utilisant switchMap, seuls les 5s sont émis, car les 3 sont annulés.

6
répondu Alexander Ciesielski 2016-09-22 09:23:28

déjà répondu en détail, mais jetez un oeil à tout ça et que vous n'oublierez jamais ce qui est switchmap

https://www.youtube.com/watch?v=rUZ9CjcaCEw

2
répondu Suresh Nagar 2018-07-03 00:41:11