我是rxjs的新手并且正在努力处理异常处理。
采用以下代码
let sub = new Subject();
let observer1:Observer<String> = {
next : v => {
console.log("next1-" + v);
if(v==='fail') {
throw new Error("fail1");
}
},
error : e => console.error("error1-" + e),
complete : () => console.log("complete1")
};
sub.subscribe(observer1);
try {
sub.next("msg1");
sub.next("msg2");
sub.next("fail");
sub.next("msg3");
} catch(e) {
console.log("Caught:" + e);
}
console.log("That's all");
据我所知,在异常之后,主题基本上已经死了,msg3永远不会成功。
我似乎无法弄清楚如何捕获Observer下一个方法中抛出的异常。
我得到的输出是
> next1-msg1 next1-msg2 next1-fail That's all
> /Users/peter/playground/rxjsstuff/node_modules/rxjs/internal/util/hostReportError.js:9
> setTimeout(function () { throw err; });
> ^
>
> Error: fail1
> at Object.next (/Users/peter/playground/rxjsstuff/dist/rxjs1.js:97:19)
> at SafeSubscriber.__tryOrUnsub (/Users/peter/playground/rxjsstuff/node_modules/rxjs/internal/Subscriber.js:263:16)
> at SafeSubscriber.next (/Users/peter/playground/rxjsstuff/node_modules/rxjs/internal/Subscriber.js:201:22)
> at Subscriber._next (/Users/peter/playground/rxjsstuff/node_modules/rxjs/internal/Subscriber.js:139:26)
> at Subscriber.next (/Users/peter/playground/rxjsstuff/node_modules/rxjs/internal/Subscriber.js:103:18)
> at Subject.next (/Users/peter/playground/rxjsstuff/node_modules/rxjs/internal/Subject.js:63:25)
> at Object.<anonymous> (/Users/peter/playground/rxjsstuff/dist/rxjs1.js:107:9)
> at Module._compile (internal/modules/cjs/loader.js:678:30)
> at Object.Module._extensions..js (internal/modules/cjs/loader.js:689:10)
> at Module.load (internal/modules/cjs/loader.js:589:32)
我认为我错过了一些基本的东西,但我似乎找不到什么。
我想高级问题是 - 当Subject调用next时,如何处理Observer的下一个方法中抛出的错误/异常?
欢迎所有提示!
的Tx
彼得
答案 0 :(得分:0)
简短的回答是,你不能也不应该。一个可观察的来源如何知道观察者可以抛出哪种错误?
答案很长,RxJS中的错误处理在版本6中已经发生了变化 -
如果您查看Subject
中next
的实施情况,您会发现没有错误处理:
next(value?: T) {
if (this.closed) {
throw new ObjectUnsubscribedError();
}
if (!this.isStopped) {
const { observers } = this;
const len = observers.length;
const copy = observers.slice();
for (let i = 0; i < len; i++) {
copy[i].next(value);
}
}
}
主题只是循环观察者,每个人都next
。
但是,每个观察者都被包裹在Subscriber
中。如果您查看subscribe
的来源,您会看到通过将观察者传递给toSubscriber
来创建Subscriber
。
特别是,创建的订阅者是SafeSubscriber
。这就是错误处理的地方。
如果您查看SafeSubscriber
中的next
,您会看到__tryOrUnsub
被调用:
next(value?: T): void {
if (!this.isStopped && this._next) {
const { _parentSubscriber } = this;
if (!config.useDeprecatedSynchronousErrorHandling || !_parentSubscriber.syncErrorThrowable) {
this.__tryOrUnsub(this._next, value);
} else if (this.__tryOrSetError(_parentSubscriber, this._next, value)) {
this.unsubscribe();
}
}
}
__tryOrUnsub
将尝试调用观察者的next
,如果发生错误,它将取消订阅观察者的来源。
__tryOrUnsub
捕获的任何错误都将使用hostReportError
报告 - 它会异步抛出错误,以便调用堆栈不会被解除。这样做是为了使一个观察者发生的错误不会影响其他观察者。
如果你向你的例子中添加第二个观察者 - 你没有抛出 - 你应该看到第二个观察者表现得像你期望的那样并且接收"msg3"
。
Ben Lesh在recent presentation中解释了这些变化及其产生的原因。你可能想看一下。