2017-06-26 1 views
0

J'ai une entrée angulaire où chaque fois que sa valeur change, je demande au service d'obtenir des données sur la valeur entrée. Je me soucie seulement de la dernière entrée entrée, donc quand l'utilisateur entre '1', mais l'efface et entre '2' je ne me soucie pas des données sur la valeur précédente. J'ai écrit quelque chose comme ça (je garde la valeur de la demande précédente prevNr):Annuler les données entrantes à partir de Observable

let stream, 
    nr = document.querySelector('input').value; 

if (status === `${nr} in progress`) { 
    stream.unsubscribe(); 
    console.log(`subscription of ${prevNr} cancelled`) 
} 

status = 'in progress'; 
prevNr = nr; 

console.log(`started subscription of ${nr}`) 
stream = someService.someMethod.subscribe(() => { 
    const clonedNr = nr; 
    setTimeout(() => { 
    status = 'done'; 
    console.log(`received response for ${clonedNr}`) 
    }, 12000); 
}) 

Ce que je reviens dans la console est

1 in progress 

subscription of 1 cancelled 
2 in progress 

subscription of 2 cancelled 
3 in progress 

subscription of 3 cancelled 
4 in progress 

received response for 1 
received response for 2 
received response for 3 
received response for 4 

En ce moment, je me moque réponse par setTimeout(), mais je peux Imaginez une situation où je reçois des données pour l'entrée 4 avant les données pour l'entrée 3 et, par conséquent, ces données seront affectées à une mauvaise entrée. Comment puis-je omettre les demandes précédentes dans Observable? Est-ce possible?

+0

La troisième fonction de rappel en subscribe est pour [achevé] (http://reactivex.io/rxjs/class/es6/Subscriber.js~Subscriber.html) – Dhyey

Répondre

0

Quelques notes:

Vous voulez probablement ajouter un debounce au flux nr. De cette façon, si l'utilisateur tape plusieurs numéros rapidement, vous n'envoyez pas de requête pour chaque numéro. debounceTime() vous permet d'attendre une quantité définie pour millisecondes après qu'une valeur est entrée, si aucune nouvelle valeur n'est entrée dans cette heure, il est transmis. Si une nouvelle valeur est entrée dans le délai défini, l'heure sera réinitialisée; rincez et répétez.

Vous ne devriez pas faire async travail dans le subscribe(), il "sorte de" casse Rx. Tout le travail asynchrone devrait être fait avant subscribe() à l'intérieur d'un autre opérateur; très souvent un des opérateurs *Map().


Je suppose someMethod() retourne une observable (ou vous pouvez probablement le convertir en un) et dans ce cas, vous voulez l'opérateur switchMap(). Vous retournez un observable à l'intérieur switchMap() et il ne s'abonnera qu'à l'observable le plus récent. Il se désinscrira également de l'observable précédent.

let stream, 
nr = document.querySelector('input').value 
    .debounceTime(500); // This will wait 500 ms before passing on a value 
         // If a new value arrives before 500ms has passed, it resets the time 

stream = nr 
    .switchMap(num => someService.someMethod(num)) 
    .subscribe(clonedNr => console.log(`received response for ${clonedNr}`));