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

来源:互联网 发布:腾讯体育直播for mac 编辑:程序博客网 时间:2024/05/16 05:09

本文为阅读《深入浅出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';        });    }};

0 0
原创粉丝点击