一:JavaScript中的发布订阅
首先我们有这么一个需求
function ajax(url, callback) {
// 实现省略
}
ajax("./test1.json", function(data) {
console.log(data);
ajax("./test2.json", function(data) {
console.log(data);
ajax("./test3.json", function(data) {
console.log(data);
});
});
});
在开发中经常会遇到这种嵌套模式,很恶心,那怎么可以解决提升耦合度呢?
如下:
// 发布订阅应用
function ajax(url, callback) {
// 实现省略
console.log(url);
}
// PubSub()是用于发布订阅的类
const pbb = new PubSub();
ajax("./test1.json", function(data) {
// 在callback中发布我们的test1Success事件
pbb.publish("test1Success", data);
});
// 订阅我们的test1Success事件
pbb.subscribe("test1Success", function(data) {
// 当test1Success被发布时触发
console.log(data);
ajax("./test2.json", function(data) {
// 再次订阅事件2
pbb.publish("test2Success", data);
});
});
// 同理
pbb.subscribe("test2Success", function(data) {
console.log(data);
ajax("./test3.json", function(data) {
pbb.publish("test3Success", data);
});
});
pbb.subscribe("test2Success", function(data) {
console.log(data);
});
其中有一个叫做PubSub的类,我们来简单理解一下PubSub。
class PubSub {
// 事件中心,用对象来存储
constructor() {
this.events = {};
}
// 发布事件
publish(eventName, data) {
// 如果事件存在
if(this.events[eventName]){
// 拿到这个事件对应的数组去遍历.
// 首先为什么是数组,因为发布的这个事件可以有多个函数去订阅它
this.events[eventName].forEach(cb => {
// 遍历数组每一项fun,即订阅它的函数,然后去执行
// 简单来说,就是把cb这个类中的属性创建到我们发布事件中去,当发布事件触发,即会继续触发它的订阅事件.
cb.apply(this, data)
});
}
}
//订阅事件
subscribe(eventName, callback) {
// 首先看一下我们有没有存储这个事件
if (this.events[eventName]) {
// 把我们的处理回调函数加进对应的函数数组中去即可
this.events[eventName].push(callback);
} else {
// 如果没有,新建数组,把处理函数直接放进去
this.events[eventName] = [callback];
}
}
// 取消订阅事件
unSubcribe(eventName, callback) {
// 如果有这个事件
if (this.events[eventName]) {
// 做过滤
this.events[eventName] = this.events[eventName].filter(
// 找到这个事件的处理回调函数,直接过滤
cb => cb !== callback
);
}
}
}
二:node.js中的发布订阅
同样,我们有这么一个例子
function readFilesByCallback() {
const fs = require("fs");
const events = require("events");
// EventEmitter是事件触发与事件监听功能的封装.产生事件的对象都是events.EventEmitter的实例
const emitter = new events.EventEmitter();
const files = [
"/Users/kitty/testgenerator/1.json",
"/Users/kitty/testgenerator/2.json",
"/Users/kitty/testgenerator/3.json"
];
fs.readFile(files[0], function(err, data) {
console.log(data.toString());
fs.readFile(files[1], function(err, data) {
console.log(data.toString());
fs.readFile(files[2], function(err, data) {
console.log(data.toString());
});
});
});
}
readFilesByCallback();
又是出现同样的嵌套关系,没关系,看下面
function readFile() {
const fs = require("fs");
//引入events模块,它下面只有一个对象,就是EventEmitter
const EventEmitter = require("events").EventEmitter;
// 实例化一个EventEimitter对象
const emitter = new EventEmitter();
fs.readFile("/Users/kitty/test.json", "utf8", function(err, data) {
if (err) {
// 通过emit发布error事件
emitter.emit("error");
return;
}
// 发布success事件
emitter.emit("success", data.toString());
});
return emitter;
}
const emitter = readFile();
// 监听success事件
emitter.on("success", function(data) {
console.log(data);
});
// 监听error事件
emitter.on("error", function(data) {
console.log("error");
});
关于node.js的还不是理解很深,暂且先记一下笔记,之后再修改和详细内容