关于RxJS Subject的学习笔记(5)

以上代码运行后,控制台的输出结果:

A 0
B 0
C 0
A 1
Rx.min.js:74 Uncaught Error: oops

JSBin - Subject Problem Demo

在代码运行前,大家会认为观察者B 会在接收到 1 值时抛出异常,观察者 A 和 C 仍会正常运行。但实际上,在当前的 RxJS 版本中若观察者 B 报错,观察者 A 和 C 也会停止运行。那么应该如何解决这个问题呢?目前最简单的方式就是为所有的观察者添加异常处理,更新后的代码如下:

const source = Rx.Observable.interval(1000);
const subject = new Rx.Subject();

const example = subject.map(x => {
  if (x === 1) {
    throw new Error('oops');
  }
  return x;
});

subject.subscribe(
  x => console.log('A', x),
  error => console.log('A Error:' + error)
);
  
example.subscribe(
  x => console.log('B', x),
  error => console.log('B Error:' + error)
);

subject.subscribe(
  x => console.log('C', x),
  error => console.log('C Error:' + error)
);

source.subscribe(subject);

JSBin - RxJS Subject Problem Solved Demo

RxJS Subject & Observable

Subject 其实是观察者模式的实现,所以当观察者订阅 Subject 对象时,Subject 对象会把订阅者添加到观察者列表中,每当有 subject 对象接收到新值时,它就会遍历观察者列表,依次调用观察者内部的 next() 方法,把值一一送出。

Subject 之所以具有 Observable 中的所有方法,是因为 Subject 类继承了 Observable 类,在 Subject 类中有五个重要的方法:

  • next - 每当 Subject 对象接收到新值的时候,next 方法会被调用
  • error - 运行中出现异常,error 方法会被调用
  • complete - Subject 订阅的 Observable 对象结束后,complete 方法会被调用
  • subscribe - 添加观察者
  • unsubscribe - 取消订阅 (设置终止标识符、清空观察者列表)

BehaviorSubject

BehaviorSubject 定义

BehaviorSubject 源码片段

export class BehaviorSubject extends Subject {
  constructor(_value) { // 设置初始值
    super();
    this._value = _value;
  }
  get value() { // 获取当前值
    return this.getValue();
  }
  _subscribe(subscriber) {
    const subscription = super._subscribe(subscriber);
    if (subscription && !subscription.closed) {
      subscriber.next(this._value); // 为新的订阅者发送当前最新的值
    }
    return subscription;
  }
  getValue() {
    if (this.hasError) {
      throw this.thrownError;
    }
    else if (this.closed) {
      throw new ObjectUnsubscribedError();
    }
    else {
      return this._value;
    }
  }
  next(value) { // 调用父类Subject的next方法,同时更新当前值
    super.next(this._value = value);
  }
}
      

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/82.html