抛出并替换错误。但随后执行结束。如何使observable发出10个元素?
const Rx = require('rxjs/Rx')
Rx.Observable.interval(1000)
.map((i) => {
if (i === 2) throw(new Error('omg'))
return i
})
.take(10)
.catch((err) => {
return Rx.Observable.of('ok, we caught an error, but we don\'t want to exit')
})
.do(console.log, console.error)
.subscribe()
答案 0 :(得分:1)
您可以提供一个处理错误的函数并返回一个observable。您需要使用flatMap
,因为您将使用更高阶的功能。
function handleError(cb){
return (val) => {
try{
return Rx.Observable.of(cb(val));
}catch(err){
console.error(`${err}`);
return Rx.Observable.empty();
}
}
}
Rx.Observable.interval(1000)
.flatMap(handleError(i => {
if (i === 2) throw(new Error('omg'))
return i;
}))
.take(10)
.do(console.log)
.subscribe()
// emits
// 0
// 1
// "Error: omg"
// 3
// 4
// 5
// 6
// 7
// 8
// 9
// 10
另一个不太适合您的示例代码但又值得一提的例子,RxJS的首席开发人员Ben Lesh在一个名为 On The Subject Of Subjects (in RxJS) 的帖子中触及了这个问题。中间有一段称为“RxJS中的陷阱”。
[...]由于Rx observables没有“陷阱”错误,我们可能遇到一些问题 这里奇怪的行为。错误“陷阱”是我自己的行为 嘲笑实施的承诺,但在多播场景中它可能 是正确的举动。当我说Rx observable没有时,我的意思是什么 “陷阱”错误基本上是当错误渗透到结束时 观察者链,如果错误未处理,它将被重新抛出。
以下是该部分的一个代码示例(最简单但效果最差):
const source$ = Observable.interval(1000)
.share()
.observeOn(Rx.Scheduler.asap); // magic here
const mapped$ = source$.map(x => {
if (x === 1) {
throw new Error('oops');
}
return x;
});
source$.subscribe(x => console.log('A', x));
mapped$.subscribe(x => console.log('B', x));
source$.subscribe(x => console.log('C', x));
// "A" 0
// "B" 0
// "C" 0
// "A" 1
// Uncaught Error: "oops"
// "C" 1
// "A" 2
// "C" 2
// "A" 3
// "C" 3
// ... etc
答案 1 :(得分:0)
我不是RxJS大师,但我想尝试回答这个问题。
使用RxJS抛出错误会终止observable。因此,您无法恢复它,但只能尝试重试/重复观察。
如果您不想重播错误,并且只能使用原始的10个元素,那么您可以return null
代替throw new Error
而filter(x => x)
take(10)
否则,您可以使用retryWhen
在出错时重复观察。请注意,这将占用2个项目,失败,然后它将重新开始重复0,1,......它在2次失败后突然出现,但仍然只需要10个项目。
Rx.Observable.interval(1000)
.map((i) => {
if (i === 2) throw(new Error('omg'))
return i
})
.retryWhen((errors) => errors.scan(
(errorCount, err) => {
if(errorCount >= 2) {
throw err;
}
return errorCount + 1;
}, 0)
)
.take(10)
.catch((err) => {
return Rx.Observable.of('ok, we caught an error, but we don\'t want to exit')
})
.subscribe((x) => console.log('result', x))
您也可以使用repeat
在观察完成后继续重复。这可能不是你想要的,但无论如何我想把它作为一个选项展示给你。您需要注意放置的位置,并且还“计算”可观察到的捕获量。
Rx.Observable.interval(1000)
.map((i) => {
if (i === 2) throw(new Error('omg'))
return i
})
.catch((err) => {
return Rx.Observable.of('ok, we caught an error, but we don\'t want to exit')
})
.repeat()
.take(10)
.subscribe((x) => console.log('result', x))
答案 2 :(得分:0)
可观察合约为OnNext*(OnError|OnCompleted)+
。
一旦序列结束,下游运营商必须取消订阅。您只能重新订阅管道。如果您的observable很冷,那么您可以使用retry
运算符重新订阅。
observable
.retry()
.take(10)
.subscribe()