您的位置:首页 > Web前端 > Node.js

nodejs中的事件机制以及事件协作和雪崩问题的改进方法

2016-06-17 11:37 579 查看

本文为阅读《深入浅出node.js》后总结部分内容而得。文中代码皆来源于该书

简单事件机制

通过事件机制,我们不用关心组件内部是怎样的,只需要关注在我们所需的事件点即可。

比如以下代码:

var options = {
host: 'wwww.google.com',
port: 80,
path: '/upload',
method: 'POST'
};
var req = http.request(option, function(res) {
console.log('STATU:' + res.statusCode);
console.log('HEADERS:' + JSON.stringify(res.header));
res.setEncoding('utf8');
res.on('data', function(chunk) {
console.log('BODY:' + chunk);
});
});
req.on('error', function(e) {
console.log('problem with request:' + e.message);
});
req.write('data\n');
req.write('data\n');
requestAnimationFrame.end()
在实现以上代码的过程中,我们不需要了解req的内部流程,只需要知道error,data这些业务事件点。

注意:在nodejs中,当我们对一个事件添加了超过10个侦听器,nodejs会发出警告,因为设计者认为侦听器太多会导致内存泄漏。

多事件协作

加入我们一个操作需要对多个事件进行操作,比如在渲染页面时,我们通过同时向多个数据源发送请求,为了实现‘当是三个事件都完成后,才执行下一操作’,程序可能会写成这样
api.getUser('username', function(profile) {
api.getTimeline('username', function(timeline) {
api.getSkin('username', function(skin) {
//todo
});
});
});
可是这种层层嵌套的形式,就会导致上一个请求完成后才进行下一个请求,无法最大化利用底层api服务器。为了解决这种多事件协作,我们可以使用github上的EventProxy模块(地址:https://github.com/JacksonTian/eventproxy)
使用eventProxy模块实现上述功能的代码如下:
var proxy = new EventProxy();
proxy.all('profile', 'timeline', 'skin', function(profile, timeline, skin) {//all方法的作用是保证执行完三个方法后,执行回调函数并传入方法接收到的数据
//todo
});
api.getUser('username', function(profile) {
proxy.emit('timeline', timeline);
});
api.getSkin('username', function(skin) {
proxy.emit('skin', skin);
});

利用事件队列解决雪崩问题

  雪崩问题就是在浏览器缓存失效后,并发访问量大量涌入数据库执行查询操作,导致数据库无法同时承受如此大的访问量,从而影响网站效果。在nodejs中一句数据库查询的代码为:
var select = function(callback) {
db.select('SQL', function(results) {
callback(results);//比如传入的函数是展示数据,那么该句的作用就是将查询后返回的数据展示出来
});
};
那么在该代码上,做一些改进,添加一个状态锁,以防止大规模并发,改进代码为:
var status = 'ready';
var select = function (callback) {
if (status === 'ready') {
status = 'pending';
db.select('SQL', function (results) {
callback(results);//比如传入的函数是展示数据,那么该句的作用就是将查询后返回的数据展示出来
status = 'ready';
});
}
};
但是改代码虽然避免了并发查询数据库操作,却导致并发的几个操作只有第一个操作被执行,后面几个不了了之,故该方法仍需改进,为更好的解决并发问题,我们仍然可以使用eventProxy模块,将所有并发操作放入一个等待队列,代码如下:
var proxy = new EventProxy();
var status = 'ready';
var select = function (callback) {
proxy.once('selected', callback);//将该实例的该操作放入队列,并且操作只执行一次
if (status === 'ready') {
status = 'pending';
db.select('SQL', function (results) {
proxy.emit('selected',results);//将该操作返回的数据作为回调函数的输入参数,执行回调函数
status = 'ready';
});
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: