2013-08-02 39 views
5

Tôi có một vấn đề hành viLàm thế nào để xử lý các ngoại lệ về một chủ đề hành vi

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

sau đó tôi quá trình đó nguồn với một cái gì đó giống như

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

Tôi muốn đăng ký vào withErrors theo cách như vậy mà tôi có thể bỏ qua các lỗi . Một nỗ lực bắt được như thế này.

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

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

và sau đó gọi nó như vậy

var withoutErrors = SkipError(withErrors); 

các Skip là một nỗ lực để tránh lặp lại những lỗi cuối cùng về vấn đề hành vi nhưng than ôi nó không hoạt động theo cách đó. Bỏ qua không bỏ qua các lỗi nhưng chỉ trên dữ liệu hợp lệ để lỗi từ trạng thái hiện tại trong chủ đề hành vi tiếp tục.

Có cách thông minh bằng văn bản Bỏ qua cũng sẽ bỏ qua các lỗi. Một cái gì đó nói với tôi điều này là không thể nhưng hy vọng tôi là sai

+1

Thực ra tôi đã đi đến kết luận rằng điều này là không thể đạt được. Theo thông số RX, một Observable không thể tiếp tục sau khi gọi OnError, bạn không thể làm gì để nhận giá trị tiếp theo sau khi OnError được gọi. Tôi sẽ cần phải chèn một số logic đến nơi trước khi lỗi được tạo ra. – bradgonesurfing

+1

Chính xác. Câu hỏi của bạn là xung đột trực tiếp với thông số Rx. Lưu ý ở đây nó không phải là BehaviorSubject mà lỗi, nhưng chiếu (Chọn nhà điều hành), không phải là rất có liên quan. –

+0

Tôi đã nhận ra rằng nếu tôi muốn truyền bá lỗi như thế này, tôi cần IObservable > trong đó Đặc biệt được định nghĩa như https://gist.github.com/bradphelan/6154972 và về cơ bản là một vùng chứa có thể chứa Ngoại lệ hoặc Giá trị – bradgonesurfing

Trả lời

2

Vì tiền đề của câu hỏi là sai, tôi trình bày một cách better để làm điều này bằng cách sử dụng Exceptional<T> đơn nguyên. Ví dụ

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); 

và chỉ để cho vui bạn có thể làm

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

mà sẽ tạo một ngoại lệ giữ giá trị "xxxzzz". Nếu bất kỳ bước nào thực hiện một ngoại lệ thì nó sẽ ngắn mạch và chỉ giữ ngoại lệ.

Việc triển khai của tôi dựa trên một câu trả lời SO khác là https://gist.github.com/bradphelan/6154972

+0

có, một cách để giải quyết vấn đề là biến ngoại lệ thành dữ liệu. Khác là để nắm bắt và tiêu thụ ngoại lệ mà không để cho họ thoát ra khỏi mã của bạn. Cả hai lược đồ đều cho phép bạn quyết định chính xác phần nào của mã của bạn có thể tiếp tục chạy không bị hỏng nếu xảy ra ngoại lệ. – Brandon

Các vấn đề liên quan