2017-01-05 1 views
1

Ein Kollege und ich haben einen Redux beobachtbaren Fluss zu unserer Android-Anwendung hinzugefügt und können nicht herausfinden, wie man ein Epic erstellt, das den Empfang von Aktionen bis zum Abschluss des ersten Aufrufs stoppt.Epic, die Aktion ignoriert, bis die erste Anfrage abgeschlossen ist

Ursprünglich dachte ich, wir könnten skipUntil() verwenden, aber dann festgestellt, dass das Ergebnis von skipUntil() geschluckt und nie an den Rest der Kette weitergegeben wird.

Unten ist ein grober JS-Code, der zeigt, was wir zu erreichen hoffen.

const fetchUserEpic = action$ => 
    action$.ofType(FETCH_USER) 
    .skipUntil(/* first request completes */) 
    .mergeMap(action => 
     ajax.getJSON(`/api/users/${action.payload}`) 
     .map(response => fetchUserFulfilled(response)) 
     .takeUntil(action$.ofType(FETCH_USER_CANCELLED)) 
    ); 

Es ist fast wie ich einen skipMap() Betreiber benötigen, die wie switchMap() wirkt aber ehrt nur eine Anforderung zu einem Zeitpunkt, während alle Elemente nicht berücksichtigt werden, wenn eine beobachtbare ist noch nicht abgeschlossen.

Vielen Dank für Anregungen.

Antwort

2

Angenommen, Sie ziemlich sicher sind, dass das, was man braucht (es ist in der Regel nicht, den Eingang fallen, während Sie eine vorherige Abfrage ausführen, bedeutet das Ergebnis veraltet ist, switchMap und/oder debounce sind in der Regel bevorzugt), take(1) + repeat sollte funktionieren, wie die Aktion beobachtbar ist heiß.

const fetchUserEpic = action$ => 
    action$.ofType(FETCH_USER) 
    .take(1) 
    .concatMap(action => 
     ajax.getJSON(`/api/users/${action.payload}`) 
     .map(response => fetchUserFulfilled(response)) 
     .takeUntil(action$.ofType(FETCH_USER_CANCELLED)) 
    ) 
    .repeat() 

Hier ist ein Schnipsel simuliert die Logik.

// simulate action$.ofType(FETCH_USER) every second 
 
const obs1 = Rx.Observable.interval(1000).publish() 
 
obs1.connect() 
 

 
function getStuff(i) { 
 
    return Rx.Observable.timer(i*1000).mapTo(i) 
 
} 
 

 
obs1.take(1).concatMap(getStuff).repeat().subscribe(console.log)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.0.2/Rx.js"></script>

+0

Danke. Ich werde es versuchen. Der Anwendungsfall, an den wir denken, ist, wenn der Benutzer schnell auf eine Senden-Schaltfläche klickt oder versucht, Daten zu aktualisieren, bevor die ursprüngliche Antwort die Chance hatte, zurückzukehren. – jachenry

+1

Vielleicht deaktivieren Sie die Schaltfläche Senden, während die Anfrage inflight ist eine bessere/sicherere Option (basierend auf dem Zustand, in FETCH_USER gesetzt, zurückgesetzt in FETCH_FULLFILLED/CANCELLED) – Gluck

1

Sie brauchen nichts Besonderes zu tun, gibt es bereits ein Betreiber für diese exhaustMap genannt. exhaustMap ist ähnlich wie concatMap, mit der Ausnahme, dass Anforderungen, die während der Verarbeitung des vorherigen Prozesses eingehen, automatisch gelöscht werden.

const fetchUserEpic = action$ => 
    action$.ofType(FETCH_USER) 
    .exhaustMap(action => 
     ajax.getJSON(`/api/users/${action.payload}`) 
     .map(response => fetchUserFulfilled(response)) 
     .takeUntil(action$.ofType(FETCH_USER_CANCELLED)) 
    ); 
+0

@jachenry Auspuffkarte ist auf jeden Fall die idiomatische – jayphelps

+0

@jayphelphs Wissen Sie, ob dort ist ein Äquivalent für Rxjava? Wird nicht in der Dokumentation angezeigt. – jachenry

+0

@jachenry gibt es kein Äquivalent. Würde einen benutzerdefinierten Operator benötigen. – jayphelps

Verwandte Themen