2017-12-02 2 views
2

Ich möchte eine Bedingung in FlatMap haben, die überprüft, was von ersten beobachtbar zurückgegeben wurde. Wenn Bedingung nicht erfüllt wird, möchte ich brechen und zu anderer Seite navigieren.rxjs Bedingung innerhalb der Flatmap

this.service.getData(id) 
    .flatMap((data) => { 
    if (!data) { 
     return Observable.throw(new NoDataFoundError()); 
    } 
    return Observable.forkJoin(
     this.service.getData2(id2), 
     this.service.getData3(id3), 
    ); 
    }) 
    .subscribe(
    ([data2, data3]) => { 
     this.data2= data2; 
     this.data3= data3; 
    }, 
    (err) => { 
     if (err instanceof NoDataFoundError) { 
     this.router.navigate(...); 
     } 
    } 
); 

Derzeit spezifische Fehler ich das Werfen und Fangen es aber ich diese Lösung nicht gefällt, wie es der Code nicht das einzige Stück ist, das einen Fehler werfen könnte und wenn skaliert nicht.

Ich dachte über Filter oder TakeWhile-Operatoren, aber ich kann die Umleitung nicht ausführen.

Ich dachte auch über die Rückkehr Observable.of statt zu werfen (in Zeile 4), aber dann würde ich tun müssen, wenn in abonnieren, die auch riecht.

+0

Der Code sieht ziemlich gut, wie sie ist. Könnten Sie bitte Ihre Bedenken erläutern? Es gibt ein paar verschiedene Muster, die Sie verwenden könnten, aber es hängt davon ab, was sonst noch passiert. –

Antwort

6

Sie können this.router.navigate und return Observable.empty() innerhalb .flatMap ausführen. Auf diese Weise haben Sie eine einzige if Aussage.

.flatMap(data => { 
    if (!data) { 
    this.router.navigate(...); 
    return Observable.empty(); 
    } 
    return (...); 
}) 

Aber in der Regel Observable sollte faul und rein sein (frei von Nebenwirkungen), wird dies sie vorhersehbar und leicht zu komponieren machen. Nebenwirkungen sollten nur vom Abonnenten durchgeführt werden.

In Ihrem speziellen Fall, wie es scheint, die richtige Lösung, um diese Logik zu setzen in der Route des Hut sein würde, wie hier beschrieben - https://stackoverflow.com/a/39162538/3772379

+2

Danke für die Antwort und Entschuldigung für die späte Antwort. Ich bin mir nicht sicher über Observable.empty() als dann müsste ich es in Subscribe. Ich finde, dass Observables rein sein sollten, aber ich denke, mein Anwendungsfall ist ziemlich verbreitet. Ich lasse mich schließlich von canActivate inspirieren, ändere es aber zu [resolver] (https://angular.io/guide/router#fetch-data-before-navigating). Danke für die Hilfe. – kit

+0

Nein, das ist der Trick. Wenn Sie '.empty()' zurückgeben, wird nichts ausgegeben, was bedeutet, dass Sie es nicht in subscribe behandeln müssen. –

+0

In meinem speziellen Problem kann ich canActivate/Resolver verwenden, die Abruflogik in der Hierarchie nach oben verschieben. Wie kann ich fortfahren, wenn ich keinen der genannten Mechanismen habe? Die einzige Lösung, die ich mir vorstellen kann, ist subscribe inside subscribe. – kit