抑制可观察管道中的异常

时间:2019-10-04 11:08:46

标签: javascript rxjs

假设我希望可观察对象定期发出值,直到另一个可观察对象发出为止。因此,我可以使用timertakeUntil来达到目的。 但是然后我想处理每个发出的值,并在某些条件变为真时停止发出(错误)消息。所以我写了下一段代码:

const { timer, Subject } = 'rxjs';
const { takeUntil, map } = 'rxjs/operators';

const s = new Subject();
let count = 0;
function processItem(item) {
  count++;
  return count < 3;
}

const value = "MyValue";

timer(0, 1000).pipe(
      takeUntil(s),
      map(() => {
        if (processItem(value)) {
          console.log(`Processing done`);
          return value;
        } else {
          s.next(true);
          s.complete();
          console.error(`Processing error`);
          throw new Error(`Stop pipe`);
        }
      }),
    )

Playground

但是我没有完成错误,而是完成了Observable。 仅当我注释掉takeUntil(s)运算符时,我才会出错。 看起来当管道运算符完成时,它的值不会立即发出,而是会在管道的下一个“迭代”结束时记住并发出,然后由新结果替换,依此类推。在我的情况下,takeUntil防止了应该发出错误的下一次迭代。我的假设是正确的吗?如果是这样,为什么以这种方式设计rxjs?

1 个答案:

答案 0 :(得分:0)

首先,每个Rx链可以发出一个error或一个complete通知,但不能同时发出。 (请参见http://reactivex.io/documentation/contract.html部分“合同管理通知” )。

takeUntil运算符在通知时发出complete。Observable(在您的情况下为s)发出任何next通知。这意味着当s发出时,链将完成,并且您将永远不会再收到任何error通知。

最后一件事,也许是最令人困惑的是,除非您需要花费时间(例如delay运算符)或将observeOn运算符与异步调度程序配合使用,否则RxJS中的所有操作都是同步发生的。因此,当您在s.next(true)内部调用map时,此next通知会立即传播到takeUntil,这将完成链,如上所述,您可以收到一个error或一个complete通知,但不会同时出现。

看起来您甚至不需要使用takeUntil,因为如果您在map内抛出错误,它会自动包装并作为error通知进一步发送({{3 }}),并且该链会自动处理,因此没有必要再用takeUntil完成它。