2017-03-27 15 views
2

有了承诺,我们可以使用变体.then在发生错误时分割链。下面是使用fetch在RxJS中发生错误可分割

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); 

一个例子这让我跳过响应处理逻辑,只会在原有取声明中提出的错误回应。东西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运营商,因为它不具有相同的行为,我的诺言链。

我知道我可以通过自定义操作符来获得它,包括实现或合并一个错误捕捉observable与这个,但这一切似乎是非常重大的矫枉过正。有没有简单的方法来实现承诺链行为?

回答

6

其实,如果我在你的情况下,我不会担心从flatMapmap捕捉错误。当源Observable抛出一个错误时,它将被传播给观察者。所以打电话时我只用一个错误处理程序订阅(否则错误被重新抛出):

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

注意,当在源可观察(许诺你的情况)出现错误,它的传播为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()运算符),那么Subject里面可能有一些我应该知道的特定行为,但在你的用例中可能并不重要。

+0

我想区分这两种错误的原因是因为我可以合理地恢复,或者从'fetch'中的错误(例如您的网络出现问题)提供某种反馈。 如果在flatMap或map中发生错误,可能是我自己的错误,所以我想让错误传播给订阅者。 – Pinpickle

+0

我喜欢你的解决方案,但我的目标是让结果(在这种情况下,来自错误或解析JSON的字符串)成为相同可观察部分。你会建议合并这两个吗? – Pinpickle

+1

比我可能在'Observable.fromPromise()'后面使用'catch()'并且用我自己的错误类('catch()')包装错误,也可以用你自己的错误类重新抛出错误为'error信号)。后来在观察者中,我可以检查错误是typeof还是实现了某个类。这意味着我可以检查错误是否发生在'fromPromise'中,并且被catch()或者来自例如catch。 'map'并且是一个常规错误。也许看看'retryWhen()'操作符也会捕获错误,但让我们根据自己的通知自动重新订阅... – martin