美文网首页
#1 Subject 的基本概念

#1 Subject 的基本概念

作者: JamesSawyer | 来源:发表于2018-03-09 10:22 被阅读13次

通常我们碰到的Observable 和 observer 都是一一对应的,多个observers 即使订阅相同的observable,它们之间也是独立的,不会共享数据或者事件,比如下例

示例1·

var observable = Rx.Observable.interval(1000).take(3);

# 观察者A
var observerA = {
  next: function(x) { console.log('观察者A ' + x);},
  error: function(err) { console.log(err); },
  complete: function() { console.log('A完成'); }
}

observable.subscribe(observerA); # 观察者A订阅observable 相当于执行函数

# 观察者B
var observerB = {
  next: function(x) { console.log('观察者B ' + x);},
  error: function(err) { console.log(err); },
  complete: function() { console.log('B完成'); }
}

setTimeout(() => {
  observable.subscribe(observerB); # 观察者B订阅相同的observable 相当于执行函数
}, 2000)

打印结果

"观察者A 0"
"观察者A 1"
"观察者B 0"
"观察者A 2"
"A完成"
"观察者B 1"
"观察者B 2"
"B完成"

可以看出观察者B虽然2秒后订阅相同的observable,但是完全不受观察者A的影响,仍然从0开始然后结束。

但是有时候我们希望流(即Observable)的数据或者事件在多个观察者之间是共享的,这个时候 Subject 就该登场了

Subject 的特点,它既是一个Observable(拥有所有Observable该拥有的操作符和方法,以及能够被别的观察者订阅的能力),又是Observer(拥有next, error, complete等方法),就是这么强悍的能力,可以把它看成一个数据的桥梁

Subject 的基本实现

上面的示例中我们看到因为订阅相当于函数执行,上面订阅了2次,所以函数执行了2次,如果想要函数只执行1次,我们可以通过一个桥梁,将所有订阅者收集到一个集合里面,然后再订阅1次,即函数只执行一次

示例2

var observable = Rx.Observable.interval(1000).take(3);

var bridgeObserver = {
  next: function(x) {
    this.observers.forEach(o => o.next(x));
  },
  error: function(err) {
    this.observers.forEach(o => o.error(err));
  },
  complete: function() {
    this.observers.forEach(o => o.complete());
  },
  observers: [],  // 观察者集合
  addObserver: function(observer) { // 将观察者添加到观察者集合中
    this.observers.push(observer)
  }
}

var observerA = {
  next: function(x) { console.log('观察者A ' + x);},
  error: function(err) { console.log(err); },
  complete: function() { console.log('A完成'); }
}

observable.subscribe(bridgeObserver); // 只订阅一次 所以相当于函数只执行一次

bridgeObserver.addObserver(observerA); // observerA添加到观察者集合中

var observerB = {
  next: function(x) { console.log('观察者B ' + x);},
  error: function(err) { console.log(err); },
  complete: function() { console.log('B完成'); }
}

setTimeout(() => {
  bridgeObserver.addObserver(observerB); // observerB添加到观察者集合中
}, 2000)

打印结果


Console Run  Clear
"观察者A 0"
"观察者A 1"
"观察者B 1"
"观察者A 2"
"观察者B 2"
"A完成"
"B完成"

可以看出观察者B共享了A中的事件,并没有从头开始执行

将上面的桥梁bridgeObserve换成 subject, addObserver 换成 subscribe 即为我们通常所见的Subject的基本骨架了

var observable = Rx.Observable.interval(1000).take(3);

var subject = {  // **`bridgeObserve`**换成 **`subject`**, 
  next: function(x) {
    this.observers.forEach(o => o.next(x));
  },
  error: function(err) {
    this.observers.forEach(o => o.error(err));
  },
  complete: function() {
    this.observers.forEach(o => o.complete());
  },
  observers: [],
  subscribe: function(observer) { // **`addObserver`** 换成 **`subscribe`** 
    this.observers.push(observer)
  }
}

var observerA = {
  next: function(x) { console.log('观察者A ' + x);},
  error: function(err) { console.log(err); },
  complete: function() { console.log('A完成'); }
}

observable.subscribe(subject); // subject作为observer的功能 能够订阅observable

subject.subscribe(observerA); // subject作为observable的功能 能够被其它observer订阅

var observerB = {
  next: function(x) { console.log('观察者B ' + x);},
  error: function(err) { console.log(err); },
  complete: function() { console.log('B完成'); }
}

setTimeout(() => {
  subject.subscribe(observerB)  // subject作为observable的功能 能够被其它observer订阅
}, 2000)

最后Rx为我们提供了这个桥梁称之为 Subject, 所以上面的代码等同于

var observable = Rx.Observable.interval(1000).take(3);

// var subject = {
//   next: function(x) {
//     this.observers.forEach(o => o.next(x));
//   },
//   error: function(err) {
//     this.observers.forEach(o => o.error(err));
//   },
//   complete: function() {
//     this.observers.forEach(o => o.complete());
//   },
//   observers: [],
//   subscribe: function(o) {
//     this.observers.push(o)
//   }
// }

// RxJS给我们提供了这样一个接口
var subject = new Rx.Subject(); 

var observerA = {
  next: function(x) { console.log('观察者A ' + x);},
  error: function(err) { console.log(err); },
  complete: function() { console.log('A完成'); }
}

observable.subscribe(subject);

subject.subscribe(observerA)

var observerB = {
  next: function(x) { console.log('观察者B ' + x);},
  error: function(err) { console.log(err); },
  complete: function() { console.log('B完成'); }
}

setTimeout(() => {
  subject.subscribe(observerB)
}, 2000)

相关文章

  • #1 Subject 的基本概念

    通常我们碰到的Observable 和 observer 都是一一对应的,多个observers 即使订阅相同的o...

  • Changing the subject 1

    转换话题包括突然把讨论转向不同的方向。并不是每次转换都构成一种错误。新的方向可能更有前景。或者也许它是一种...

  • Changing the subject 1

    转移话题包括将讨论突然性地转向为某个不同的方向。不是每种转换都构成某个错误。新的方向也许会更有希望。或许会提供即时...

  • 无标题笔记

    * subject 1

  • Unit3

    1. subject 1.1 形近词 subjectiveadj. 主观的,个人的be subject to 遭受...

  • RxJS 学习系列 15. Subject 示例

    这节举几个例子来加强 Subject 的理解 例1 理解 Subject 的组播 Subject 是一个特殊的对...

  • 学科课程与活动课程 | fen解知识点

    1 学科课程 学科课程(subject curriculum),又叫学科主题课程(subject matter c...

  • Learn RxSwift---2.subjects

    1.RxSwift中Subject subject是Observable和observer之间的桥梁,一个subj...

  • RxJava学习(1)-Subject

    前言 根据Froussios英文版的学习笔记,这里是简单的学习笔记。如果对于subject的文档看不懂,可以进入这...

  • shiro安全认证流程

    流程:1.创建secuirtyManager。2.创建subject3.subject.login(密匙)安全认证...

网友评论

      本文标题:#1 Subject 的基本概念

      本文链接:https://www.haomeiwen.com/subject/uppxmxtx.html