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)
))
);
}
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 ).
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 project
i => ...
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
.
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.
Son déjà répondu et en détail, mais jetez un oeil à cela et vous n'oublierez jamais ce qui est switchmap
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.
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.
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.
Source: observables ES6 dans RxJS