关于 RxJS 错误处理方式的说明:"The observable data type disallows the exception from leaking from the stream's context"

Clarification about RxJS way of handling errors: "The observable data type disallows the exception from leaking from the stream's context"

我参考了 Manning 出版商的 RxJS in action 一书,它提供了以下示例代码来演示 RxJS 的方式处理错误:

const computeHalf = x => Math.floor(x / 2);

Rx.Observable.of(2,4,5,8,10)
   .map(num => {
      if(num % 2 !== 0) {
        throw new Error(`Unexpected odd number: ${num}`); //#A
      }
      return num;
   })
   .map(computeHalf)
   .subscribe(
       function next(val) {
          console.log(val);
       },
       function error(err) {
          console.log(`Caught: ${err}`); //#B
       },
       function complete() {
          console.log('All done!');
       }
    );

书上接着说到 RxJS:

errors don't escape the observable pipeline.

也有不同的说法:

The observable data type disallows the exception from leaking from the stream's context.

有人可以解释一下这与使用传统 try/catch 处理错误有何不同(就副作用而言)如下?

try {
 someDangerousFunction();
}
catch(error){
 console.log(error.message);
}

与前者相比,后一个样本如何产生副作用?

上面两句引号是什么意思?

这意味着当您在调用 subscribe(.., error => ...) 时设置错误处理程序时,异常只会传递给错误处理程序,而不会传递给其他任何东西(您抛出异常但被 RxJS 捕获)。

这就是 "errors don't escape the observable pipeline.""leaking" 的意思,我认为它们的意思相同。

在您发布的示例中,您在 map() 中抛出了一个错误,该错误被 map() 自动捕获并作为错误通知发送。

所以你通常不会用 try/catch 包装 Observable 链。需要注意的一件重要事情是,如果您的 subscribe 调用未设置并且错误处理程序比重新抛出错误可能会破坏您的应用程序。在这种情况下,您可能想使用 try/catch,但使用错误处理程序总是更容易。

我认为它是为了与 Promise 形成对比,而不是与 try/catch 形成对比。针对 Promise 进行编码时,常见错误是...

doSomeAsyncTask().then(rsp => {
  doSomeOtherAsyncTask(rsp).then(rsp2 => {
    myButton.label = rsp2.text;
  });
}).catch(err => {
  console.log(err);
});

人们可能认为他们正在捕获错误,但如果 doSomeOtherAsyncTask 抛出某些错误,它实际上不会传播。当然,有一些方法可以避免这种情况,但如果您是 promises 的新手,这是一个很容易犯的错误。