2016-07-29 59 views
24

我有一個要解析的項目列表,但其中一個解析可能會失敗。RxJs捕獲錯誤並繼續

什麼是 「RX-路」 搭上錯誤,但繼續執行序列

代碼示例:

var observable = Rx.Observable.from([0,1,2,3,4,5]) 
 
.map(
 
    function(value){ 
 
     if(value == 3){ 
 
     throw new Error("Value cannot be 3"); 
 
     } 
 
    return value; 
 
    }); 
 

 
observable.subscribe(
 
    function(value){ 
 
    console.log("onNext " + value); 
 
    }, 
 
    function(error){ 
 
    console.log("Error: " + error.message); 
 
    }, 
 
    function(){ 
 
    console.log("Completed!"); 
 
    });
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.6/rx.all.js"></script>

我想在非的Rx做什麼-Way:

var items = [0,1,2,3,4,5]; 
 

 
for (var item in items){ 
 
    try{ 
 
    if(item == 3){ 
 
     throw new Error("Value cannot be 3"); 
 
    } 
 
    console.log(item); 
 
    }catch(error){ 
 
    console.log("Error: " + error.message); 
 
    } 
 
}

在此先感謝

+0

請參閱Rx.Observable.onErrorResumeNext –

+0

看到它,但不能使它以這種方式工作......請問您能寫一個例子嗎? – Cheborra

+0

參見[Ben Leshs談論這個](https://youtu.be/3LKMwkuK0ZE?t=20m17s),特別是在23:43。 – LPL

回答

0

您可以實際使用的try/catch裏面你地圖功能來處理錯誤。這裏是代碼片段

var source = Rx.Observable.from([0, 1, 2, 3, 4, 5]) 
 
    .map(
 
     function(value) { 
 
      try { 
 
       if (value === 3) { 
 
        throw new Error("Value cannot be 3"); 
 
       } 
 
       return value; 
 

 
      } catch (error) { 
 
       console.log('I caught an error'); 
 
       return undefined; 
 
      } 
 
     }) 
 
    .filter(function(x) { 
 
     return x !== undefined; }); 
 

 

 
source.subscribe(
 
    function(value) { 
 
     console.log("onNext " + value); 
 
    }, 
 
    function(error) { 
 
     console.log("Error: " + error.message); 
 
    }, 
 
    function() { 
 
     console.log("Completed!"); 
 
    });
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.6/rx.all.js"></script>

31

我會建議你(在rxjs 5版現在mergeMap),而不是使用flatMap,這將讓你崩潰的錯誤,如果你不關心他們。實際上,您將創建一個內部Observable,如果發生錯誤,它可以被吞噬。這種方法的優點是可以將運算符鏈接在一起,並且如果在管道中的任何位置發生錯誤,它將自動轉發到catch塊。

var observable = Rx.Observable.from([0, 1, 2, 3, 4, 5]) 
 
    .flatMap((value) =>   
 
    Rx.Observable.if(() => value != 3, 
 
     Rx.Observable.just(value), 
 
     Rx.Observable.throw(new Error("Value cannot be 3"))) 
 
    //This will get skipped if upstream throws an error 
 
    .map(v => v * 2) 
 
    .catch((err) => { 
 
     console.log("Caught Error, continuing") 
 
     //Return an empty Observable which gets collapsed in the output 
 
     return Rx.Observable.empty(); 
 
    }) 
 
); 
 

 
observable.subscribe(
 
    (value) => console.log("onNext " + value), (error) => console.log("Error: " + error.message),() => console.log("Completed!") 
 
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.6/rx.all.js"></script>

+0

不確定OP實際要求什麼,但是這個(或其變體)似乎是最通用的方法。 –

+0

在新的API中適合與'mergeMap'一起使用 – bhantol

+0

如果在'flatMap'之後的某個鏈上出現錯誤,該怎麼辦? – nonybrighto

16

你需要切換到一個新的一次性流,如果發生錯誤,這將會被安全處置,並保留原始流活着:

Rx.Observable.from([0,1,2,3,4,5]) 
 
    .switchMap(value => { 
 

 
     // This is the disposable stream! 
 
     // Errors can safely occur in here without killing the original stream 
 

 
     return Rx.Observable.of(value) 
 
      .map(value => { 
 
       if (value === 3) { 
 
        throw new Error('Value cannot be 3'); 
 
       } 
 
       return value; 
 
      }) 
 
      .catch(error => { 
 
       // You can do some fancy stuff here with errors if you like 
 
       // Below we are just returning the error object to the outer stream 
 
       return Rx.Observable.of(error); 
 
      }); 
 

 
    }) 
 
    .map(value => { 
 
     if (value instanceof Error) { 
 
      // Maybe do some error handling here 
 
      return `Error: ${value.message}`; 
 
     } 
 
     return value; 
 
    }) 
 
    .subscribe(
 
     (x => console.log('Success', x)), 
 
     (x => console.log('Error', x)), 
 
     (() => console.log('Complete')) 
 
    );
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.4.1/Rx.min.js"></script>

有關此技術的更多信息,請參閱此博客文章:The Quest for Meatballs: Continue RxJS Streams When Errors Occur

+1

這應該是被接受的答案,因爲即使發現錯誤也會完成流 - 一旦完成,流將永遠不會發射另一個事件。 – kayjtea

+0

那可以用可排序和管道操作符來看看? –