RxJS - 抓住并继续

时间:2015-05-22 09:38:43

标签: javascript system.reactive rxjs

我正在努力以我期望的方式处理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)
});

1 个答案:

答案 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函数。