四. Observerble 是什么
整个RxJS的基础就是 Observable,只要弄懂Observable就算学会一半的RxJS了,
剩下的只是对一些方法的练习.
要理解 Observable,必须先谈谈两个设计模式,
迭代器模式(Iterator Pattern) 跟 观察者模式(Observer Pattern)
Observer Pattern 观察者模式
最简单的观察者模式就是DOM对象的事件监听.
function clickHandler(event) {
console.log('user click!');
}
document.body.addEventListener('click', clickHandler)
// 首先声明一个clickHandler函数
// 再调用 addEventListener 来注册监听click事件,clickHandler 就是监听者(listener)
// body发生click事件时,通知所有注册的监听者事件发生,并传入 event,监听者函数 自动执行.
// 这就是观察者模式. 观察者模式的概念其实就是这么简单
// 代码的关键点,事件的注册监听与通知,都已经被观察者类做好了,而不用自己编写.
下面来练习写一个观察者类,或者说构造函数
// ES5
function Producer() {
if(!(this instanceof Producer)) { // 避免使用者直接当函数来调用
throw new Error('请用 new Producer()!');
}
this.listeners = [];
}
// 给观察者类,加入注册listener的方法,listener只是一个个用户定义的回调函数.
Producer.prototype.addListener = function(listener) {
if(typeof listener === 'function') this.listeners.push(listener)
else throw new Error('listener 必須是 function')
}
// 加入移除listener的方法,listener由使用者编写,写的是事件发生后要进行的操作.
Producer.prototype.removeListener = function(listener) {
this.listeners.splice(this.listeners.indexOf(listener), 1)
}
// 事件发生时的通知方法,其实就是拿出所有listener,传参让其执行.
Producer.prototype.notify = function(message) {
this.listeners.forEach(listener => {
listener(message);
})
}
Promise 的实现就是使用的观察者模式
// ES6
class Producer {
constructor() {
this.listeners = [];
}
addListener(listener) {
if(typeof listener === 'function') this.listeners.push(listener)
else throw new Error('listener 必須是 function')
}
removeListener(listener) {
this.listeners.splice(this.listeners.indexOf(listener), 1)
}
notify(message) {
this.listeners.forEach(listener => {
listener(message);
})
}
}
// 使用
var egghead = new Producer();
// new 出一个 Producer 实例叫 egghead
function listener1(message) {
console.log(message + 'from listener1');
}
function listener2(message) {
console.log(message + 'from listener2');
}
egghead.addListener(listener1); // 注册监听事件
egghead.addListener(listener2);
egghead.notify('A new course!!') // 发生事件时调用notify方法.
总结
观察者就是一个拥有注册监听,移除监听,通知监听者,三个方法的对象.
所有监听者调用观察者对象上的方法注册监听,当事件发生时调用观察者对象的通知方法
通过观察者这个中介, 做到了 事件 与 监听者 两者间的解耦.
Iterator Pattern 迭代器模式
迭代器(Iterator) 是一个对象,就像一个指针(pointer),指向一个队列(sequence)结构的数据.
下面写一个简单的迭代器构造函数.
// JS在ES6开始才原生支持 Iterator
function IteratorFromArray(arr) {
if(!(this instanceof IteratorFromArray)) {
throw new Error('请用 new IteratorFromArray()!');
}
this._array = arr;
this._cursor = 0;
}
IteratorFromArray.prototype.next = function() {
return this._cursor < this._array.length ?
{ value: this._array[this._cursor++], done: false } :
{ done: true };
}
// ES6 实现
class IteratorFromArray {
constructor(arr) {
this._array = arr;
this._cursor = 0;
}
next() {
return this._cursor < this._array.length ?
{ value: this._array[this._cursor++], done: false } :
{ done: true };
}
}
迭代器 相当于一个拥有 next方法 的数组,
一直调用 next方法 会返回当前下标的数据,并将指针指向下一下标,
直到迭代器的 指针指向最后一个元素之后,返回{ done: true, value: undefined}
迭代器有两大优点,
可以做延迟执行(Lazy evaluation).便于处理异步操作.
作为类数组对象, 可以加入很多循环方法, 如map,filter等.
Lazy evaluation 延迟执行
延迟一个表达式的执行 直到真正需要它的值时 才执行.
// ES6的generator函数,可终端执行的函数
function* getNumbers(words) {
for (let word of words) {
if (/^[0-9]+$/.test(word)) {
yield parseInt(word, 10);
}
}
}
const iterator = getNumbers('30 天精通 RxJS (04)');
// 此时变量iterator 得到的是 getNumbers 第一次执行到yield时,暂停并返回的迭代器
iterator.next(); // 此时第一次执行 yield 后的 parseInt(word, 10)
// 结果作为next()方法的返回值返回,{ value: 3, done: false }
// 并将iterator继续执行到下一个yield 然后暂停.
iterator.next(); // { value: 0, done: false }
iterator.next(); // { value: 0, done: false }
iterator.next(); // { value: 4, done: false }
iterator.next(); // 执行到无yield,并且 函数执行完毕(return),
// 包括这次 及之后每次执行next,都返回 { value: undefined, done: true }
每次调用next()时, 才会执行后面的代码. 这种情况就是延迟执行.
Observable 总结
Observer 和 Iterator 有个共通的特性,就是都是渐进式的取得数据.
差别只在于
Observer 是生产者(Producer)推送数据(push),
Iterator 是消费者(Consumer)要求数据(pull)!
// Observer 事先注册好拿到数据要干什么,而不知道什么时候会获取到数据,
// 由事件自动触发,被动接收数据,并执行.
// 生产者知道什么时候有数据,所以由生产者推送,并触发回调.(异步)
body.addEventListener('click', (event) => {})
// iterator 去主动调用,立即获取数据,然后执行.(同步)
var x = iterator.next()
Observable,其实是两者的结合,由生产者推送资料(异步,响应式),
同时又像队列一样拥有map,filter等方法…
Observable 就像一个队列,里面的元素会随着时间推送(原话).
我的理解:
Observable 就像 链式调用,
里面的异步操作在完成时 自动触发(生产者推送) 已经注册好的回调(Observer),
回调完成后会根据返回值 主动发起(消费者要求) 下一个数据请求(Iterator),
然后再等 异步/同步 执行完毕 自动触发 已经注册好的回调,
以此循环,直到链式调用执行完毕.
(暂定解析,猜测如此,后期学完修复)
Rx.Observable
.fromEvent(document.body, 'click') // 註冊監聽
.take(1) // 只取一次
.subscribe(console.log);
Observable 这一小段没有彻底明白,有点模糊,只做了思路整理.