理解JavaScript、node.js中的发布和订阅模式以及运用

一: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的还不是理解很深,暂且先记一下笔记,之后再修改和详细内容

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值