我正在努力以我期望的方式处理Rx错误。
当我有一个Observable(例如,来自点击流)并且发生异常时我想抓住它但继续。我试过的所有解决方案都会捕获错误然后结束Observable。有没有办法捕捉和继续?
作为一个例子,下面的Observable将发出“1”,然后是“Error”,但从不发出“3”。
var range = Rx.Observable.range(1,3)
.map(function(i){
if(i === 2){
throw "Error";
} else {
return i;
}
})
.catch(function(e){
return Rx.Observable.return(e)
});
range.subscribe(function(i){
console.log(i)
});
答案 0 :(得分:9)
虽然由于Observable合约(OnNext)* (OnCompleted|OnError)
而无法实现您的预期行为,但通过引入热门Observable,可以通过实际方法正确解决此问题。
let hotRange = Rx.Observable.range(1,3).publish();
let safeRange = hotRange
.map(function (i) {
if (i === 2) {
throw "Error";
} else {
return i;
}
})
.retry();
safeRange.subscribe(i => console.log(i));
hotRange.connect();
See the JSBin。你在问题中提到的range
Observable是一个冷的Observable。它是behaves as a movie,所以如果发生错误并且我们重新订阅,我们需要从“电影”的开头订阅,即1
然后"Error"
。
你可能有一个隐含的假设,Rx.Observable.range(1, 3)
是一个实时的Observable,即“热”。由于不是,我使用hotRange
在上方publish()
。这样,它将独立于其订户发出其事件。如果我们希望能够在发生错误后“继续”,我们需要我们的源(“hotRange”)没有错误。这就是为什么range.map( )
不是热门的Observable。 retry()
会在hotRange.map( )
上发现错误,并将其替换为hotRange.map( )
。由于hotRange
很热,retry()
的每次执行都会有所不同,因为它不记得hotRange
发出的先前值。因此,当2
导致的错误在重试中被hotRange.map( )
替换时,hotRange
将随后发出3
,并且无错误地传递map函数。