2017-08-07 4 views
4

Ich habe einen Anwendungsfall, wo ich auf eine Folge von Aktionen warten muss, bevor ich einen anderen mit Redux Observables senden. Ich habe einige ähnliche Fragen gesehen, aber ich kann mir nicht vorstellen, wie ich diese Ansätze für meinen gegebenen Anwendungsfall verwenden kann.Warten auf Reihenfolge der Aktion mit einem Redux Observable

Im Grunde möchte ich etwas tun, wie so:

action$ 
    .ofType(PAGINATION_CLICKED) // This action occurred. 
    .ofType(FETCH_SUCCESS) // Then this action occurred after. 
    .map(() => analyticsAction()); // Dispatch analytics. 

ich auch FETCH_ERROR Brände zum Beispiel, wenn eine andere Aktion des Typs immer wieder diese Sequenz abzubrechen und starten möchten.

Antwort

7

Große Frage. Der wichtige Punkt ist, dass action$ ein Hot/Multicast-Stream aller Aktionen ist, wie sie gesendet werden (es ist ein Betreff). Da es heiß ist, können wir es mehrfach kombinieren und alle hören den selben Strom von Aktionen.

// uses switchMap so if another PAGINATION_CLICKED comes in 
// before FETCH_SUCCESS we start over 

action$ 
    .ofType(PAGINATION_CLICKED) 
    .switchMap(() => 
    action$.ofType(FETCH_SUCCESS) 
     .take(1) // <-------------------- very important! 
     .map(() => analyticsAction()) 
     .takeUntil(action$.ofType(FETCH_ERROR)) 
); 

Also jedes Mal, wenn wir erhalten PAGINATION_CLICKED wir an dieser inneren beobachtbare Kette hören beginnen werden, die für einen einzelnen FETCH_SUCCESS hört. Es ist wichtig, dass .take(1) zu haben, denn sonst würden wir weiterhin auf mehr als eine FETCH_SUCCESS hören, die seltsame Fehler verursachen könnte, und selbst wenn nicht, ist es in der Regel die beste Vorgehensweise, nur das zu nehmen, was Sie brauchen.

Wir verwenden takeUntil, um das Warten auf FETCH_SUCCESS abzubrechen, wenn wir zuerst FETCH_ERROR erhalten.


Als Bonus, wenn Sie Sie auch entscheiden, wollen einige Analysen Material auch auf der Grundlage des Fehlers zu tun, nur nicht von vorne beginnen, können Sie race zu der Tat Rennen zwischen den beiden Strömen verwenden. Der erste, der ausstrahlt, gewinnt; der andere ist abgemeldet.

action$ 
    .ofType(PAGINATION_CLICKED) 
    .switchMap(() => 
    Observable.race(
     action$.ofType(FETCH_SUCCESS) 
     .take(1) 
     .map(() => analyticsAction()), 
     action$.ofType(FETCH_ERROR) 
     .take(1) 
     .map(() => someOtherAnalyticsAction()) 
    ) 
); 

Hier ist die gleiche Sache, aber race als Instanz Operator anstelle des statisch verwenden. Dies ist eine stilistische Vorliebe, die Sie wählen können. Beide machen das Gleiche. Verwenden Sie das, was Ihnen klarer ist.

action$ 
    .ofType(PAGINATION_CLICKED) 
    .switchMap(() => 
    action$.ofType(FETCH_SUCCESS) 
     .map(() => analyticsAction()) 
     .race(
     action$.ofType(FETCH_ERROR) 
      .map(() => someOtherAnalyticsAction()) 
    ) 
     .take(1) 
); 
+0

Ich bin fast da! Ich landete mit Ihrem ersten Beispiel, aber ohne das (jetzt offensichtlich kritische) 'take (1)'. Dies bedeutete im Grunde, dass die "Sequenz" nach dem ersten "PAGINATION_CLICKED" ignoriert wurde. Vielen Dank, tolle Unterstützung für die Bibliothek :) –

+1

Gern geschehen! Prost. – jayphelps

Verwandte Themen