it-swarm.com.de

RxJS wie man einen Fehler mit catch ignoriert und weitermacht

Hallo, ich habe den folgenden Code und möchte wissen, wie ich verhindern kann, dass das Haupt- (Upstream-) Observable gelöscht wird, wenn ein Fehler ausgelöst wird.

Wie kann ich den folgenden Code so ändern, dass alle Zahlen "4" erwarten?

Ich suche eine allgemeine Musterlösung, die in anderen Fällen mit anderen Operatoren funktionieren würde. Dies ist der einfachste Fall, den ich mir vorstellen konnte.

const Rx = require('rxjs/Rx');

function checkValue(n) {
  if(n === 4) {
    throw new Error("Bad value");
  }
  return true;
}
const source = Rx.Observable.interval(100).take(10);

source.filter(x => checkValue(x))
  .catch(err => Rx.Observable.empty())
  .subscribe(v => console.log(v));
5
devguy

Sie möchten, dass die Quellbeobachtungsdatei weiterhin ausgeführt wird. Wenn Sie jedoch den Fehler im Hauptereignisstream zulassen, wird die gesamte Beobachtungsdatei ausgeblendet und Sie erhalten keine Elemente mehr.

Die Lösung besteht darin, einen getrennten Strom zu erstellen, in dem Sie filtern und auffangen können, ohne dass die vorgelagerte Leitung kollabiert.

const Rx = require('rxjs/Rx');
function checkValue(n) {
  if(n === 4) {
    throw new Error("Bad value");
  }
  return true;
}
const source = Rx.Observable.interval(100).take(10);

source
  // pass the item into the projection function of the switchMap operator
  .switchMap(x => {
     // we create a new stream of just one item
     // this stream is created for every item emitted by the source observable
     return Observable.of(x)
       // now we run the filter
       .filter(checkValue)
       // we catch the error here within the projection function
       // on error this upstream pipe will collapse, but that is ok because it starts within this function and will not effect the source
       // the downstream operators will never see the error so they will also not be effect
       .catch(err => Rx.Observable.empty());
     })
     .subscribe(v => console.log(v));

Sie können auch das zweite Argument verwenden, das an den catch-Selektor übergeben wird, um die beobachtbare Quelle neu zu starten. Dadurch wird sie jedoch so gestartet, als ob sie noch nicht ausgeführt worden wäre.

const Rx = require('rxjs/Rx');

function checkValue(n) {
  if(n === 4) {
    throw new Error("Bad value");
  }
  return true;
}
const source = Rx.Observable.interval(100).take(10);

source.filter(x => checkValue(x))
  .catch((err, source) => source)
  .subscribe(v => console.log(v));

Damit wird aber nicht der gewünschte Effekt erzielt. Sie sehen einen Stream, der bis zum Ende der Zeit wiederholt 1..3 ausgibt ... oder Sie fahren das Skript herunter. Welches auch immer zuerst kommt. (Dies ist wichtig, was .retry() macht)

9

Sie müssen einen flatMap-Operator verwenden, um die Filterung durchzuführen. In der flatMap in diesem Beispiel verwende ich Observable.if (), um die Filterung durchzuführen, da es mir garantiert, dass ich die ganze Zeit Observables zurückgebe. Ich bin mir sicher, dass Sie es auch anders machen können, aber das ist eine saubere Implementierung für mich.

const source = Rx.Observable.interval(100).take(10).flatMap((x)=>
    Rx.Observable.if(() => x !== 4, 
    Rx.Observable.of(x),
    Rx.Observable.throw("Bad value"))
    .catch((err) => {
        return Rx.Observable.empty()
    })
);

source.subscribe(v => console.log(v));
0
zinyando