js 四种异步变成模式:回调函数、事件监听、发布订阅模式、promise(yield/await),其实事件监听跟发布订阅模式很像,也是触发函数调用(回调函数),所以前三者有很大的相似之处。
1.类的解耦
发布订阅者模式,对象或者类的解耦!
const Oberver = (function () {
// 防止消息队列暴露而被篡改个,故将消息容器作为静态私有变量保存
const _messages = {};
return {
// 注册信息接口
regist(type, fn) {
if (typeof _messages[type] === 'undefined') {
_messages[type] = [fn];
} else {
_messages[type].push(fn);
}
return this;
},
// 发布信息接口
fire(type, msg) {
if (!_messages[type]) {
return;
}
// 发布的消息
const event = {
type,
msg
}
for (let i = 0; i < _messages[type].length; i++) {
// _message不能被 垃圾回收机制 回收 产生闭包, 内存不会被释放,泄漏中...
_messages[type][i].call(this, event);
// _messages[type][i](event); // 不替换this暂时也可以
}
},
// 移除信息接口
remove(type, fn) {
// 如果 消息类型(消息动作序列)存在
if (_messages[type] instanceof Array) {
let i = _messages[type].length - 1;
for (; i >= 0; i--) {
// 如果存在 ‘该动作’ 则 在消息动作序列 移除相应动作
_messages[type][i] === fn && _messages[type].splice(i, 1);
}
}
return this;
}
}
})();
// 实际测试使用
// A订阅一个test1
Oberver.regist('test1', function (e) {
console.log('我是A用户');
console.log(e);
});
// B订阅一个test1
Oberver.regist('test1', function (e) {
console.log('我是B用户');
console.log(e);
})
// 监听着开始发布
Oberver.fire('test1', {
data: '通知,公司来了MM啊!'
});
2.组件通信
通过观察者模式我们可以解决团队开发过程中的模块间通信,这是模块间解耦的一种可行性方案
const Observer = (function () {
// 消息队列
const _message = {};
return {
regist(type, fn) { // 订阅、注册、监听
if (!Array.isArray(_message[type])) { // 类型不存在
_message[type] = [fn];
} else {
_message[type].push(fn);
}
},
fire(type, data) { // 发布消息
const res = {
type,
data
}
if (!Array.isArray(_message[type])) {
return;
}
for (let i = 0; i < _message[type].length; i++) {
_message[type][i].call(this, res);
}
},
remove(type, fn) { // 移除订阅、注册、监听
if (!Array.isArray(_message[type])) {
return;
}
let len = _message[type].length,
i = _message[type].length - 1;
for (; i >= 0; i--) {
_message[type][i] === fn && _message[type].splice(i, 1);
}
}
}
})();
// 实际使用----------------------------------------->
// 创建学生类
function Student(result) {
var that = this;
this.result = result;
this.say = function (e) {
// console.log(e);
console.log(that.result);
}
};
Student.prototype.answer = function (question) {
// 注册监听 在父级上
Observer.regist(question, this.say);
}
Student.prototype.sleep = function (question) {
// 取消监听 在父级上
Observer.remove(question, this.say);
}
// 创建老师类
function Teacher() {};
Teacher.prototype.ask = function (question) {
console.log('老师发布的问题是:' + question);
Observer.fire(question,{msg:'真棒!'})
}
// 创建机器学生
const student1 = new Student('学生1开始回答问题');
const student2 = new Student('学生2开始回答问题');
const student3 = new Student('学生3开始回答问题');
// 学生监听问题类型
student1.answer('什么是设计模式');
student1.answer('发布订阅这模式是?');
student2.answer('什么是设计模式');
student2.answer('发布订阅这模式是?');
student3.answer('什么是设计模式');
student3.answer('发布订阅这模式是?');
// 但是有学生睡着了(down机了)取消注册、订阅、监听
student2.sleep('发布订阅这模式是?');
student3.sleep('什么是设计模式');
// -------------老师正式开始提问---------->
const techer = new Teacher();
techer.ask('什么是设计模式'); // 类型1
techer.ask('发布订阅这模式是?'); // 类型2