node.js中事件通知机制的两个应用场景

应用场景

上篇博客介绍了几个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);
});

时间: 2024-09-16 18:44:53

node.js中事件通知机制的两个应用场景的相关文章

node.js中的事件处理机制详解_node.js

EventEmitter类 在Node.js的用于实现各种事件处理的event模块中,定义了一个EventEmitter类.所有可能触发事件的对象都是一个集成了EventEmitter类的子类的实例对象,在Node.js中,为EventEmitter类定义了许多方法,所有与对象的事件处理函数的绑定及解除相关的处理均依靠这些方法的调用来执行. EventEmitter类的各种方法 event:代表事件名 listener:代表事件处理函数 中括号内的参数代表该参数为可选参数 方法名与参数 描述 a

Node.js中的模块机制学习笔记_node.js

Javascript自诞生以来,曾经没有人拿它当做一门编程语言.在Web 1.0时代,这种脚本语言主要被用来做表单验证和网页特效.直到Web 2.0时代,前端工程师利用它大大提升了网页上的用户体验,JS才被广泛重视起来.在JS逐渐流行的过程中,它大致经历了工具类库.组件库.前端框架.前端应用的变迁.Javascript先天就缺乏一项功能:模块,而CommonJS规范的出现则弥补了这一缺陷.本文将介绍CommonJS规范及Node的模块机制. 在其他高级语言中,Java有类文件,Python有im

Node.js中HTTP模块与事件模块详解_node.js

Node.js的http服务器 通过使用HTTP模块的低级API,Node.js允许我们创建服务器和客户端.刚开始学node的时候,我们都会遇到如下代码: 复制代码 代码如下: var http = require('http'); http.createServer(function (req,res) {     res.end('Hello World\n'); }).listen(3000,"127.0.0.1"); console.log("Server funni

Node.js中的流(Stream)介绍

 这篇文章主要介绍了Node.js中的流(Stream)介绍,本文讲解了什么是流.pipe方法.流的分类.Readable流状态的切换等内容,需要的朋友可以参考下     什么是流? 说到流,就涉及到一个*nix的概念:管道--在*nix中,流在Shell中被实现为可以通过 |(管道符) 进行桥接的数据,一个进程的输出(stdout)可被直接作为下一个进程的输入(stdin). 在Node中,流(Stream)的概念与之类似,代表一种数据流可供桥接的能力. pipe 流化的精髓在于 .pipe(

Node.js中内存泄漏分析

内存泄漏(Memory Leak)指由于疏忽或错误造成程序未能释放已经不再使用的内存的情况.如果内存泄漏的位置比较关键,那么随着处理的进行可能持有越来越多的无用内存,这些无用的内存变多会引起服务器响应速度变慢,严重的情况下导致内存达到某个极限(可能是进程的上限,如 v8 的上限:也可能是系统可提供的内存上限)会使得应用程序崩溃. 传统的 C/C++ 中存在野指针,对象用完之后未释放等情况导致的内存泄漏.而在使用虚拟机执行的语言中如 Java.JavaScript 由于使用了 GC (Garbag

在Node.js中使用HTTP上传文件的方法

  这篇文章主要介绍了在Node.js中使用HTTP上传文件的方法,作者以windows下的visual studio作为操作node的环境,推荐阅读!需要的朋友可以参考下 开发环境 我们将使用 Visual Studio Express 2013 for Web 作为开发环境, 不过它还不能被用来做 Node.js 开发.为此我们需要安装 Node.js Tools for Visual Studio. 装好后 Visual Studio Express 2013 for Web 就会转变成一

浅谈Node.js中的定时器

  本文给大家分享的是Node.js中的定时器的相关资料,十分的全面细致,有需要的小伙伴可以参考下. Node.js中定时器的实现 上一篇博文提到,在Node中timer并不是通过新开线程来实现的,而是直接在event loop中完成.下面通过几个JavaScript的定时器示例以及Node相关源码来分析在Node中,timer功能到底是怎么实现的. JavaScript中定时器功能的特点 无论是Node还是浏览器中,都有setTimeout和setInterval这两个定时器函数,并且其工作特

关于在 Node.js 中引用模块,知道这些就够了

本文讲的是关于在 Node.js 中引用模块,知道这些就够了, Node 提供了两个核心模块来管理模块依赖: require 模块在全局范围内可用,不需要写 require('require'). module 模块同样在全局范围内可用,不需要写 require('module'). 你可以将 require 模块理解为命令,将 module 模块理解为所有引入模块的组织者. 在 Node 中引入一个模块其实并不是个多么复杂的概念. const config = require('/path/t

Node.js中Process.nextTick()和setImmediate()的区别

一.Webstrom使用node.js IDE的问题 在区别这两个函数之前来说一下Webstrom使用node.js IDE的问题,在配置Node.js的IDE了,但setImmediate().require等这些node.js中内置的函数时并不会有提示,要解决这个问题只要设置一下Webstrom,File---->Setting---->Languages&Frameworks------>Node.js and NPM中的Node.js core Library is no