2017-11-19 2 views
1

Der folgende Code effektiv Versprechung Auflösung Versprechen zu true und ein Versprechen Fehler zu false.RxJS: Karte Versprechen Ergebnis und Versprechen Fehler zu verschiedenen Werten

onlineUpdate$ 
.switchMap(online => { 
    switch (online) { 
    default: 
    case true: { 
     const connected$ = new Rx.Subject(); 
     axios.get("/some/url/to/test/connection") 
     .then(response => connected$.next(true)) 
     .catch(error => connected$.next(false)); 
     return connected$; 
    } 
    case false: { 
     return Rx.Observable.of(false); 
    } 
    } 
}); 

Aber etwas über die Zwischen Rx.Subject Schaffung fühlt sich an wie ich mehr Arbeit machte, als ich brauche. Gibt es eine elegantere oder eingebaute Möglichkeit, die Versprechensauflösung auf einen Wert abzubilden und einem anderen einen Fehler zu versprechen, ohne die Verwendung eines Zwischenprodukts Rx.Subject oder eines anderen Observablen?

+0

Während in diesem speziellen Fall nicht viel passieren kann, würde ich immer noch [empfehlen '. dann (..., ...) 'über' .then (...) .catch (...) '] (https://stackoverflow.com/q/24662289/1048572) – Bergi

Antwort

0

Es stellt sich heraus, es gibt keine Notwendigkeit, Observable.fromPromise() überhaupt zu verwenden. Die einfachste Änderung diese Arbeit zu machen ist:

onlineUpdate$ 
.switchMap(online => { 
    switch (online) { 
    default: 
    case true: { 
     return axios.get("/some/url/to/test/connection") 
     .then(response => true) 
     .catch(error => false); 
    } 
    case false: { 
     return Rx.Observable.of(false); 
    } 
    } 
}); 

Oder, wenn Sie Ternäre über switch Aussagen bevorzugen:

onlineUpdate$ 
.switchMap(online => { 
    return online ? 
    axios.get("/some/url/to/test/connection") 
     .then(response => true) 
     .catch(error => false) 
    : Rx.Observable.of(false); 
}); 
3

Wickeln Sie das Versprechen in eine Observable über Observable#fromPromise Funktion und übergeben Sie das Versprechen in. Beobachtbar wird true emittieren, wenn das Versprechen wird aufgelöst oder false wenn es

... 
case true: { 
     return Rx.Observable.fromPromise(axios.get("/some/url/to/test/connection") 
              .then(response => true) 
              .catch(error => false)); 
    } 
... 

Einfaches Beispiel abgelehnt wird.

Rx.Observable.of(false) entspricht der case false. Promise.resolve(true) an die then Funktion des Versprechens und Promise.reject('Error').catch(err => false) an die catch Funktion des Versprechens.

Rx.Observable.of(false).subscribe(console.log); 
 
Rx.Observable.fromPromise(Promise.resolve(true)).subscribe(console.log); 
 
Rx.Observable.fromPromise(Promise.reject('Error').catch(err => false)).subscribe(console.log);
<script src="https://unpkg.com/@reactivex/[email protected]/dist/global/Rx.js"></script>

+1

Danke für die Antwort, @Suren. Das hat mir wirklich geholfen, Rx.Subject() loszuwerden. Es stellt sich jedoch heraus, dass die Verwendung von "Observable.fromPromise" mit "flatMap" oder "switchMap" nicht benötigt wird. –

1

Ja, können Sie einfach zurückgeben Observable.of(false) im catch-Block des Observable.fromPromise(). Verwenden Sie .map(), um Observable.of(true) zurückzugeben, wenn die Verbindung erfolgreich ist.

onlineUpdate$ 
    .switchMap(online => { 
     switch (online) { 
      default: 
      case true: { 
       Rx.Observable.fromPromise(axios.get("/some/url/to/test/connection")) 
        .map(() => true) // if the promise resolves to something, return an Observable.of(true) 
        .catch(() => Rx.Observable.of(false)) // else if there is any error return Observable.of(false) 
      } 
      case false: { 
       return Rx.Observable.of(false); 
      } 
     } 
    }); 

Beachten Sie, dass Sie müssen explizit .map() die Observable.fromPromise true, wenn die promise löst erfolgreich.

Sie den Code in einem viel prägnanter Weise schreiben:

onlineUpdate$ 
    .switchMap(online => { 
     return online ? 
      Rx.Observable.fromPromise(axios.get("/some/url/to/test/connection")) 
       .map(() => true) 
       .catch(() => Observable.of(false)) 
      : Observabe.of(false) 
    }); 
1

Der switchMap Operator arbeitet mit so genannten Observable input was bedeutet, können Sie einfach die Versprechen zurück, ohne es in eine beobachtbare zu drehen:

onlineUpdate$ 
.switchMap(online => { 
    switch (online) { 
    default: 
    case true: { 
     return axios.get("/some/url/to/test/connection"); 
    } 
    case false: { 
     return Rx.Observable.of(false); 
    } 
    } 
}) 
.catch(() => Rx.Observable.of(false)) 
.map(Boolean) // force convert to boolean 

Nur beachten Sie, das ist nicht das Gleiche wie das, was Sie geschrieben haben. Der Operator catch fängt alle Fehler auf, auch wenn sie nicht aus dem vorhergehenden axios.get Aufruf stammen, aber vielleicht ist es in Ihrem Fall egal.