4.Observerble 是什么


四. 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 这一小段没有彻底明白,有点模糊,只做了思路整理.


文章作者: 罗紫宇
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 罗紫宇 !
  目录