这是我参与8月更文挑战的第11天,活动详情查看:8月更文挑战
这个系列是 nodejs 的异步编程学习记录,前两篇文章是:
上一篇文章讲述了异步编程的优势和难点,这篇文章对于异步编程的难点,说明可以参考的解决方式,整体来看主要有三种方式:事件发布/订阅模式;Promise/Deferred模式;流程控制库。
这篇文章发布/订阅模式的介绍和应用。
发布/订阅模式基本介绍
发布/订阅模式是一种使用很广的设计模式,在 nodejs 中 events 模块 就是发布订阅模式的一个典型的例子。具体代码如下:
const EventEmitter = require('events');
const myEmitter = new EventEmitter();
// 订阅
myEmitter.on('event', (message) => {
console.log(`an event occurred! ${message}`);
});
// 发布
myEmitter.emit('event', 'hello!');
发布订阅模型在应用上,可以进行组件的封装,把不变的部分封装到组件内部,将容易变化,需要自定义的部分封装交由组件外部处理,是一种典型的逻辑分离方式。
以 http 请求为例,我们只需要监听 data、error、end 这些事件,并做出相应的处理,不需要关注背后的处理流程。
var options = {
host: 'www.google.com', port: 80,
path: '/upload', method: 'POST'
};
var req = http.request(options, function (res) {
res.on('data', function (chunk) {});
res.on('end', function () {});
});
req.on('error', function (e) {});
req.end();
另外,需要注意的是 nodejs 对发布/订阅模式做了一些额外的处理,如果对一个事件绑定了超过10个监听器,则会触发一条警告,因为设计者认为监听器过多可能会导致内存泄露。可以通过增加 emitter.setMaxListeners(0) 的方式把这个限制去掉;另一方面,事件监听器过多,可能会过多占用 CPU。
另外,如果在程序运行过程中触发了 error 事件,nodejs 会有一些特殊处理,首先会检查是否有 error 事件的监听器,如果没有会抛出异常,如果没有捕获这个
继承 event 模块
nodejs 中近半数的核心模块都继承自 EventEmitter,nodejs 中 utils 封装了方法,可以快速的继承 EventEmitter,使用事件机制解决业务问题,下面是 Stream 继承的例子:
var events = require('events');
function Stream() {
events.EventEmitter.call(this);
}
util.inherits(Stream, events.EventEmitter);
利用事件队列解决雪崩问题
雪崩问题是指在高并发的场景下,缓存失效,大量的请求涌入到数据库中,数据库无法承受这么大的查询请求,影响到网站的整体速度。
var select = function (callback) {
db.select("SQL", function (results) {
callback(results);
});
};
如果这站点刚启动,缓存中是没有数据的,这时如果访问量巨大,会进行大量的数据库查询,我们可以使用状态锁+发布/订阅模式解决这个问题。
var proxy = new events.EventEmitter();
var status = "ready";
var select = function (callback) {
proxy.once("selected", callback); // 每次请求新增一个订阅者,once 的意思是订阅者被触发一次后,就会将监听器移除
if (status === "ready") {
status = "pending"; // 除第一次进入请求,status 设为 pending,避免重复查询数据库
db.select("SQL", function (results) {
proxy.emit("selected", results); // 数据库查询完成后发布者发布完成的消息消息
status = "ready";
});
}
};
这样做之后,除了第一次进入之外的请求,会通过订阅者的方式,等待数据查询完成后发布消息,触发监听器,执行自己的业务逻辑。
以上是发布/订阅模式的介绍和应用,是对 深入浅出 nodejs 这本书的第四章 - 异步编程的学习笔记和练习,欢迎点赞和评论~