RxJS 中的失败映射?

Failable map in RxJS?

我来自 iOS 我曾广泛使用 ReactiveCocoa 的土地。在RAC中,当maping操作失败时,有tryMap运算符sendError

Rx.JS中是否有等价物?我可以使用 flatMap 和另一个 Observable 来模仿类似的行为,但这肯定看起来有点矫枉过正。

谢谢!

我假设您希望它在映射操作失败时结束流?我不认为它内置了 RxJS,但相当容易编写。您只需要捕获错误并让 tryMap 基本上 return 一个 Either 类型的构造,它要么是错误要么是映射结果:

Rx.Observable.prototype.tryMap = function(selector) {
  var mapSelector = function(value, index, obs) {
    try {
      return {
        value: selector(value, index, obs)
      };
    } catch (e) {
      return {
        error: e
      };
    }
  };
  return this.map(mapSelector);
};

// Usage:
Rx.Observable
  .of(1, 2, 3, 4, 5)
  .tryMap(function(v) {
    if ((v % 2) === 1) {
      throw new Error("odd numbers are evil");
    }

    return v / 2;
  })
  .subscribe(function(result) {
    if (result.error) {
      console.log("error: " + result.error.message);
    } else {
      console.log("result: " + result.value);
    }
  });
<script src="https://getfirebug.com/firebug-lite-debug.js"></script>
<script src="https://rawgit.com/Reactive-Extensions/RxJS/master/dist/rx.all.js"></script>

Brandon 的回答解释了捕获错误并将其通过 onNext 流向下传递的好方法。

我最初的问题是简单地结束流并传播 Error,这显然在 RxJS 中很好地实现了,只需 throwmap 操作块中抛出一个异常。我猜 RxJS 将整个操作包装在 try {} catch {} 块中,并通过将其发送到 Error 流来优雅地处理异常。

我写这篇文章作为来自 ReactiveCocoa 的人的参考,他们当前的实现不允许 throw 仅仅是因为 Swift 语言的限制不允许异常,这是固定在 Swift 2.

Observable.just(1)
  .map(num => { if (num == 1) { throw new Error('error') } return num; })
  .subscribeOnError(console.log) // prints 'error'