【node.js能做什么】node.js中事件通知机制的两个应用场景

更新时间:2020-11-10    来源:php入门    手机版     字体:

【www.bbyears.com--php入门】

应用场景

上篇博客介绍了几个EventEmitter的API使用,简单高效,有利于解耦业务逻辑.

通过once()方法解决雪崩问题
在事件订阅/发布模式中,通过once()方法注册的侦听器只会被执行一次,在执行之后会将它与事件的关联移除.实际开发中可以利用这点过滤一些重复性的事件响应.
例如在高访问量和大并发量的情况下,以下直接的写法可能导致数据库无法同时承受,进而影响到网站整体的响应调用:

var select = function(callback){ 
  db.select("SQL",function(results){
    callback(results);
  });
}
当然,加入状态锁可以解决并发问题,不过除了第一个请求得到响应外,其他的请求将不会得到相应:

var status = "ready"; 
var select = function(callback){ 
  if(status === "ready"){
    status = "panding";
    db.select("SQL",function(results){
      status = "ready";
      callback(results);
    });
  }
}
这时候可以引入事件队列:

var event = require("event"); 
var ee = new event.EventEmitter(); 
var select = function(callback){ 
  ee.once("selected",callback);  //注册多个只执行一次的侦听器或者可以理解为将这些存入一个队列
  if(status === "ready"){
    status = "pending";
    db.select("SQL",function(results){
      ee.emit("selected",results); //只查询一次,并将结果发射给之前注册的多个将只执行一次的侦听器
    });
  }
}
只查询一次,并将结果发射给之前注册的多个将只执行一次的侦听器,借助EventEmitter将结果发射给所有队列,并由EventEmitter帮我们处理后续各种回收问题.当然,之前介绍过,这需要配合setMaxListeners(0)移除侦听器数量限制.

使用EventEmitter解决多异步之间的协同方案
事件发布/订阅模式可以隔离业务逻辑,保持业务逻辑单元的职责单一,一般而言,事件与侦听器的关系是一对多,但在异步编程中,也会出现事件与侦听器是多对一的情况,也就是说一个业务逻辑可能依赖三个通过回调或事件传递的结果.
这里介绍渲染页面需要读取两个数据,在不使用Promise async Q等库的情况下:

var count = 0; 
var results = {}; 
var done = function(key,value){ 
  results[key] = value;
  count++;
  if(count === 3){ //三个依赖均已正常完成
    render(); //渲染页面
  }
}
db.select("SQL1",function(results){ 
  done("data1",results);
});
db.select("SQL2",function(results){ 
  done("data2",results);
});
User.get(function(err,user)){ 
  done("user",user);
});
如果使用发布/订阅模式:

var ee = new require("event").EventEmitter(); 
var after = function(times,callback){ 
  var count = 0;
  var results = {};
  return function(key,value){
    results[key] = value;
    count++;
    if(count === times){
      callback(results);
    }
  }
}
ee.on("done",after); 
db.select("SQL1",function(results){ 
  ee.emit("done",3,results);
});
db.select("SQL2",function(results){ 
  ee.emit("done",3,results);
});
User.get(function(err,user)){ 
  ee.emit("done",3,user);
});

本文来源:http://www.bbyears.com/jiaocheng/109464.html

猜你感兴趣