在RxJS中出错时拆分observable

时间:2017-03-27 02:14:21

标签: javascript promise rxjs rxjs5

使用promises,我们可以使用.then的变体在发生错误时拆分链。以下是使用fetch

的示例
fetch('http://website.com').then(
  // Perform some logic
  (response) => response.json().then(({ answer }) => `Your answer: ${answer}`),
  // Skip json parsing when an error occurs
  (error) => 'An error occurred :(',
).then(console.log);

这允许我跳过响应处理逻辑并仅响应原始fetch语句中引发的错误。 RxJS中的类似内容可能如下所示:

Observable.fromPromise(fetch('http://website.com'))
  // if I put .catch here, the result will be piped into flatMap and map
  .flatMap(response => response.json())
  .map(({ answer }) => `Your answer: ${answer}`)
  // if I put .catch here, errors thrown in flatMap and map will also be caught
  .subscribe(console.log);

作为代码状态中的注释,我不能简单地使用catch操作符,因为它没有与我的promise链相同的行为。

我知道我可以通过自定义运算符来实现它,包括实现,或合并一个错误捕获可观察到的这个,但这一切看起来都是相当重大的过度杀伤力。有没有一种简单的方法来实现承诺链行为?

1 个答案:

答案 0 :(得分:6)

实际上,如果我处于你的情况,我不会担心从flatMapmap发现错误。当源Observable抛出错误时,它将传播给观察者。所以我在调用subscribe时只使用错误处理程序(否则会重新抛出错误):

.subscribe(console.log, err => console.log('error:', err));

请注意,当源Observable(您的案例中为Promise)发生错误时,它会以error通知的形式传播,而不是标准next通知。 这意味着flatMap()map()不会对错误消息产生任何影响。如果您使用catch()materialize(),则两个运算符(flatMapmap)都必须能够处理此类数据(并且不会引发另一个错误)。

无论如何,您总是可以使用share()publish()并制作两个不同的订阅,其中每个订阅只处理一种类型的信号:

let source = Observable.fromPromise(fetch('http://website.com')).publish();

source
  .subscribe(undefined, err => console.log(err));

source
  .flatMap(...)
  .map(...)
  .subscribe(console.log, () => {});

source.connect();

现在我只有一个单独的观察者来处理错误。

请注意,我必须使用() => {}进行空回调,否则将忽略错误。另请注意,在使用多播(publish()运算符)时,主题内部可能会有一些我应该注意的特定行为,但可能在您的用例中并不重要。