web-dev-qa-db-fra.com

SwitchMap vs MergeMap dans l'exemple #ngrx

Ci-dessous, le code de l’exemple Ngrx: https://github.com/ngrx/example-app/blob/master/src/effects/book.ts Ma question est de savoir pourquoi dans le premier @Effect, il utilise switchMap tandis que les autres utilisent mergeMap. Est-ce parce que le premier @Effect concerne le réseau, et avec le switchMap, vous pouvez annuler la requête réseau précédente si elle est en cours d'exécution?

@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)
      ))
    );
}
52
Tuong Le

Vous avez raison; switchMap va se désabonner du Observable renvoyé par son argument project dès qu'il aura à nouveau appelé la fonction project pour produire un nouveau Observable.

RxJs est incroyablement puissant et dense, mais son niveau d'abstraction élevé peut parfois rendre le code difficile à comprendre. Permettez-moi de démystifier un peu les diagrammes de marbre et les documents fournis par @Andy Hole et de les mettre à jour. Vous trouverez peut-être le référence de syntaxe de marbre très utile pour mieux comprendre les opérateurs rxjs à partir de leurs tests (au moins, j’ai trouvé ceci manquant/pas assez mis en évidence dans le documentation officielle ).

fusionner la carte

mergeMap

La première ligne du diagramme est la source Observable qui émet (1,3,5) à des moments différents. La deuxième ligne du diagramme est l’observable prototype renvoyé par la fonction projecti => ... passée à l’opérateur .mergeMap().

Lorsque l'observable source émet l'élément 1, mergeMap() appelle la fonction project avec i=1. L’Observable renvoyé émettra 10 trois fois, toutes les 10 images (voir référence de la syntaxe en marbre ). La même chose se produit lorsque l'Observable source émet l'élément 3 et que la fonction project 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 renvoyé par project.

switchMap

switchMap Ceci est différent avec switchMap(), qui se désabonnera de l'observable renvoyé par project dès qu'il l'aura appelé à nouveau sur un nouvel élément. Le diagramme en marbre indique cela avec le troisième élément manquant 30 dans la sortie Observable.

Dans l'exemple que vous avez donné, cela entraîne l'annulation de la demande de recherche en attente. Ceci est une propriété très jolie mais difficile à obtenir , que vous obtenez gratuitement en combinant switchMap() avec des observables annulables. retourné par le service Http d'Angular. Cela peut vous éviter beaucoup de maux de tête sans vous soucier de la gestion correcte de toutes les conditions de concurrence qui se produisent généralement avec l'annulation asynchrone.

80
Johannes Rudolph

Son déjà répondu et en détail, mais jetez un oeil à cela et vous n'oublierez jamais ce qui est switchmap

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

7
Suresh Nagar

Vous avez raison.

Comme vous pouvez le constater, switchMap est utilisé avec la fonctionnalité de recherche. Dans cet exemple, la zone de recherche est programmée pour émettre une demande de recherche lorsque l'utilisateur saisit du texte dans la zone de texte (avec un rebond ou un délai de 350 ms).

Cela signifie que lorsque l'utilisateur entre 'har', ngrx envoie une demande de recherche au 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 par "harr").

Cela est très bien montré dans les diagrammes en marbre fournis dans une autre réponse. Dans mergeMap, les observables précédents ne sont pas annulés et par conséquent, les valeurs "30" et "50" sont mélangées. Avec switchMap, seuls les 5 sont émis car les 3 sont annulés.

7

fusionner la carte

Projette chaque valeur source dans un observable qui est fusionné dans la sortie observable.

Mappe chaque valeur sur un observable, puis aplatit tous ces observables internes en utilisant mergeAll.

enter image description here

switchMap

Projete chaque valeur source dans un observable qui est fusionnée dans la sortie Observable, émettant des valeurs uniquement à partir de l'observable le plus récemment projeté.

Mappe chaque valeur sur un observable, puis aplatit tous ces observables internes à l'aide de switch.

enter image description here

Source: observables ES6 dans RxJS

4
Andy Hoyle