buttonClicked$.pipe( switchMap(value=>makeRequest1), switchMap(responseOfRequest1=>makeRequest2)) .subscribe() I need to make 2 http request sequentially, and abort downstream pending request if the button clicks. Is the above code the right approach? I understand that a new click will cancel pending request1. if the click happens during request2, does request2 get canceled as well?
3 Réponses :
L'opérateur switchMap annule son Observable interne uniquement lorsqu'il reçoit l'événement suivant de son Observable amont (c'est-à-dire makeRequest1 ) , pas lorsque la source Observable émet (ie buttonClicked $ ). Considérez donc la séquence d'événements suivante:
buttonClicked$.pipe(
switchMap(clickValue => makeRequest1(clickValue).pipe(
mergeMap(request1Value => makeRequest2(request1Value)))
).subscribe(request2Value => /* ... */);
Dans ce scénario, car la réponse à la requête 2 est reçue avant que la deuxième réponse à la requête 1 ne soit reçue, même si le deuxième bouton clique s'est produite avant la fin de la requête 2, la requête 2 n'a jamais été annulée.
Si la requête 1 émet sa deuxième réponse avant que la requête 2 ne reçoive une réponse, alors oui, la requête 2 est annulée. Mais notez que ce n'est pas le clic sur le bouton qui l'a annulé en soi, c'est l'émission de la requête 1 qui l'a annulée.
Si vous souhaitez annuler les deux requêtes de manière fiable lorsque le est cliqué sur le bouton, les deux demandes doivent être effectuées dans la même switchMap:
first button click first request 1 sent first response to request 1 received first request 2 sent second button click second request 1 sent first response to request 2 received second response to request 1 received
Oui, ça marche comme ça avec intervalle. Je ne l'ai pas testé avec une requête réseau.
À chaque clic, le deuxième intervalle observable est redémarré.
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.4.0/rxjs.umd.min.js"></script> <button id="btn">Click Me</button> <div id="result"></div>
const { fromEvent, interval, of } = rxjs;
const { switchMap } = rxjs.operators;
const btn = document.getElementById('btn');
const result = document.getElementById('result');
const click$ = fromEvent(btn, 'click');
click$
.pipe(
switchMap(value => of('Hello')),
switchMap(value => interval(1000))
)
.subscribe(
val => result.innerText = val
)
Ce comportement est correct car switchMap se désabonne de son Observable interne uniquement lorsqu'il reçoit la notification next . Cela signifie que lorsque vous avez deux switchMap , alors le premier doit émettre en premier pour déclencher la désinscription dans le second.
Vous pouvez éviter cela en utilisant un seul switchMap code > et mettre le deuxième appel makeRequest2 dans une seule chaîne avec makeRequest1 .
buttonClicked$.pipe(
switchMap(value => makeRequest1(value).pipe(
mergeMap(responseOfRequest1 => makeRequest2(responseOfRequest1)),
)),
.subscribe()
De cette façon, lorsque buttonCliqué $ émet qu'il fait switchMap se désabonner de son Observable interne qui se désabonne également en interne mergeMap qui annulera le deuxième appel s'il est toujours en attente.
p>