Open Cuuube opened 6 years ago
之前研究了观察者模式,观察者模式是个很好的一对多的消息通知范例。
被观察者只需负责更新自己的状态。而观察者施加一个观察,然后设置一个相应行动就可以了。
这种情形在做ajax请求的时候大有可为。
在ajax中,xhr对象一次发生一次询问,根据服务器相应,会更新自身状态。这就是一个很好的观察者模式的应用。很明显的,xhr充当的是被观察者。我们需要的是一些观察者,观察到xhr状态变化后执行操作。
(xhr本身提供了事件驱动的接口。我们通过一些代码,将这些事件驱动的设计变成观察者模式的设计很容易。同理可应用于nodejs的事件驱动设计的对象。提一下这一块用于读者的举一反三。)
首先需要之前写的观察者基类。我就把基类和集成的类放在一起了。用代码注释来分割。
// 观察者模式的ajax请求 // ------- 基类 --------- // 被观察者 class Subject { constructor () { this.observerList = []; this.m_state = ''; } // 被观察者注册一个观察者 register (observer) { this.observerList.push(observer); console.log('添加一个观察者!'); } // 删除观察者 unregister (observer) { if (this.observerList.indexOf(observer) > -1) { this.observerList.splice(this.observerList.indexOf(observer), 1); console.log('删除一个观察者!'); } } // 被观察者把状态更新广播给所有观察者 boardcast (value) { this.observerList.forEach((observer) => { observer.action(value); }) } get state () { return this.m_state; } // 被改变状态状态改变。调用广播告诉所有观察者 set state (value) { this.m_state = value; this.boardcast(this.state); } } // 观察者 class Observer { constructor (subject) { this.subject = subject; } // 观察者主动观察被观察者。允许传入被观察者的数组 observe (subjects, callback) { if (!(subjects instanceof Array)) { subjects = [subjects]; } subjects.forEach((subject) => { subject.register(this); if (callback) { this.action = callback; } }) } // 动作方法 action (value) { new Error('请勿直接调用抽象类的方法!'); } } // ------- 继承 start --------- // 被观察者,核心为一个xhr。 class XHRSubject extends Subject { constructor (method, url, data, headers) { super(); // 注意,此xhr用作只用于示范。功能很贫弱。请读者自行增强ajax功能 this.xhr = new XMLHttpRequest(); this.state = ''; this.xhr.open(method, url); // xhr接收到响应后更新状态 this.xhr.onload = (res) => { this.state = res }; this.xhr.onerror = (err) => { this.state = err; }; // xhr即时发送请求。不想即时请求也可以写一个方法来发送请求,手动或者其他时机调用。 this.xhr.send(); } } // 观察者,这里写一个动作方法。或者不在类里声明动作,在实例化对象的时候增加动作方法 class Watcher extends Observer { action (res) { let data = res.currentTarget.response; console.log('资料在观察者类定义中处理'); } } // ----------- use -------------- function main() { // 实例化xhr被观察者 let xhrSub = new XHRSubject('GET', '/'); let xhrSub2 = new XHRSubject('GET', '/123'); // 实例化观察者 let watcher1 = new Watcher(); let watcher2 = new Watcher(); // “被观察者主动注册观察者”式调用 xhrSub.register(watcher1); // 观察者主动调用 watcher2.observe(xhrSub2, (res) => { let data = res.currentTarget.response; console.log('资料处理成功。资料处理方法在观察者订阅时赋予'); }); } main();
添加一个观察者! 添加一个观察者! 资料在观察者类定义中处理 GET https://www.google.com.sg/123 404 () 资料处理成功。资料处理方法在观察者订阅时赋予
上面代码可以直接在浏览器中运行,观察。
因为用到XHRHttpRequest类,所以不能在nodejs环境跑了。。。
因为只试着用观察者模式实现了ajax的使用。重点在于这种设计模式。所以请各位自行扩展ajax的功能啦~
最后。。。你听说过rxjs么?
用观察者模式实现ajax框架
简介
之前研究了观察者模式,观察者模式是个很好的一对多的消息通知范例。
被观察者只需负责更新自己的状态。而观察者施加一个观察,然后设置一个相应行动就可以了。
这种情形在做ajax请求的时候大有可为。
在ajax中,xhr对象一次发生一次询问,根据服务器相应,会更新自身状态。这就是一个很好的观察者模式的应用。很明显的,xhr充当的是被观察者。我们需要的是一些观察者,观察到xhr状态变化后执行操作。
(xhr本身提供了事件驱动的接口。我们通过一些代码,将这些事件驱动的设计变成观察者模式的设计很容易。同理可应用于nodejs的事件驱动设计的对象。提一下这一块用于读者的举一反三。)
代码
首先需要之前写的观察者基类。我就把基类和集成的类放在一起了。用代码注释来分割。
结果输出
上面代码可以直接在浏览器中运行,观察。
因为用到XHRHttpRequest类,所以不能在nodejs环境跑了。。。
因为只试着用观察者模式实现了ajax的使用。重点在于这种设计模式。所以请各位自行扩展ajax的功能啦~
最后。。。你听说过rxjs么?