2013-08-02 2 views
5

ich ein Verhalten ThemaWie Ausnahme auf einem Verhalten Thema

var source = new BehaviorSubject<int>(0); 

ich, dass dann Prozess zu handhaben Quelle mit so etwas wie

var withErrors = source 
      .Select(v => 
      { 
       if (v == 2) 
       { 
        throw new Exception("Ouch "); 
       } 
       return v; 
      }) 

ich in einer solchen Art und Weise zu withErrors abonnieren möchten, dass ich kann die Fehler überspringen. Ein Versuch mit diesem Fang.

public IObservabe<int> SkipError(IObservable<T> source){ 

    return source 
     .Catch(e=>SkipErrors(source.Skip(1)); 
} 

und dann rufen so

var withoutErrors = SkipError(withErrors); 

das Überspringen ist ein Versuch, auf das Verhalten Thema Wiederholung des letzten Fehler zu vermeiden, aber leider es nicht so funktioniert. Überspringen überspringt Fehler nicht, sondern nur über gültige Daten, so dass der Fehler vom aktuellen Zustand im Verhaltenssubjekt durchkommt.

Gibt es eine clevere Art, Skip zu schreiben, die auch Fehler überspringt. Etwas sagt mir, das ist nicht möglich, aber hoffentlich bin ich falsch

+1

Eigentlich habe ich zu dem Schluss gekommen, dass dies unmöglich ist, zu erreichen. Da nach der RX-Spezifikation ein Observable nach dem Aufrufen von OnError nicht fortgesetzt werden kann, gibt es nichts, was Sie tun können, um den nächsten Wert zu erhalten, nachdem der OnError aufgerufen wurde. Bevor der Fehler generiert wird, muss eine Logik an der Stelle eingefügt werden. – bradgonesurfing

+1

Korrekt. Ihre Frage steht in direktem Konflikt mit der Rx-Spezifikation. Beachten Sie, dass hier nicht das BehaviorSubject Fehler, sondern die Projektion (Select operator), nicht das ist sehr relevant. –

+0

Ich habe festgestellt, dass, wenn ich solche Fehler propagieren möchte ich IObservable > wo Exceptional wie https://gist.github.com/bradphelan/6154972 definiert ist und im Wesentlichen ein Container ist, die entweder eine Ausnahme halten kann oder ein Wert – bradgonesurfing

Antwort

2

Da die Prämisse der Frage falsch ist, präsentiere ich eine better Weise, dies mit der Exceptional<T> Monad zu tun. Zum Beispiel

IObservable<int> source = ....; 
IObservable<Exceptional<string>> withErrors = 
    source.Select(i=>Exceptional.Execute(()=>{ 
     if(v==2){ 
      throw new Exception("Ouch"); 
     } 
     return v.ToString(); 
    }); 


IObservable<Exception> errors = 
    withErrors.Where(v=>v.HasException).select(v=>v.Exception); 

IObservable<string> values = 
    withErrors.Where(v=>!v.HasException).select(v=>v.Value); 

und nur zum Spaß können Sie

Exceptional<string> r = 
     from x in Exceptional.Execute(() => "xxx") 
     from y in Exceptional.Execute(() => "zzz") 
     select x + y; 

tun das wird Generation ein Exceptional hält den Wert "xxxzzz". Wenn einer der Schritte eine Ausnahme auslöst, wird nur die Ausnahme kurzgeschlossen und gehalten.

Meine Implementierung basiert weg eine andere SO Antwort https://gist.github.com/bradphelan/6154972

+0

Ja, eine Möglichkeit, das Problem anzugehen, besteht darin, Ausnahmen in Daten umzuwandeln. Eine weitere Möglichkeit besteht darin, Ausnahmen zu fangen und zu konsumieren, ohne sie aus Ihrem Code zu entfernen. Mit beiden Schemas können Sie genau entscheiden, welche Teile Ihres Codes unvermindert weiterlaufen können, wenn eine Ausnahme auftritt. – Brandon

Verwandte Themen