安装

npm install eventproxy --save

调用

var EventProxy = require('eventproxy');

异步协作

多类型异步协作

此处以页面渲染为场景,渲染页面需要模版、数据。假设都需要异步读取。

  1. var EventProxy = require('eventproxy');
  2. //获取EventProxy实例
  3. var ep = new EventProxy();
  4. ep.all('tpl', 'data', function(tpl, data){//or ep.all(['tpl', 'data'], function(tpl, data{}))
  5. //在所有指定的事件触发后, 将会被调用执行
  6. //参数对应各自的事件名
  7. });
  8. fs.readFile('template.tpl', 'utf-8', function(err, content){
  9. ep.emit('tpl', content);
  10. });
  11. db.get('sql', function(err, content){
  12. ep.emit('data', result);
  13. });

all方法将handler注册到事件组合上。当注册的所有事件均触发后,将会调用handler执行,每个事件传递的数据,将会依照事件名顺序,传入handler作为参数。

快速创建

EventProxy提供了create静态方法,可以快速完成注册all事件。

  1. var ep_create = EventProxy.create('tpl', 'data', function(tpl, data){
  2. //TODO
  3. });

以上方法等效于

  1. var ep = new EventProxy();
  2. ep.all('tpl', 'data', function(tpl, data){
  3. //TODO
  4. });

重复异步协作

此处以读取目录下所有文件为例,在异步操作中,我们需要在所有异步调用结束后,执行某些操作。

  1. var ep = new EventProxy();
  2. ep.after('got_file', files.length, function(list){
  3. //在所有文件的异步执行结束后将被执行
  4. //所有文件的内容都存在list数组中
  5. });
  6. for(var i = 0; i<files.length; i++){
  7. fs.readFile(files[i], 'utf-8', function(err, content){
  8. //触发结果事件
  9. ep.emit('got_file', content);
  10. })
  11. }

after方法适合重复的操作,比如爬10个网站,读10个文件,调用5次数据库等。将handler注册到N次相同事件的触发上。达到指定的触发数,handler将会被调用执行,每次触发的数据,将会按触发顺序,存为数组作为参数传入。

持续型异步协作

此处以股票为例,数据和模版都是异步获取,但是数据会持续刷新,视图会需要重新刷新。

  1. var ep = new EventProxy();
  2. ep.tail('tpl', 'data', function(tpl, data){
  3. //待所有指定的时间都触发后,将第一次回调
  4. //以后再出发其中之一的时间,都会回调
  5. });
  6. fs.readFile('template.tpl', 'utf-8', function(err, content){
  7. ep.emit('tpl', content);
  8. });
  9. setInterval(function(){
  10. db.get('sql', function(err, result){
  11. ep.emit('data', result);
  12. });
  13. }, 2000);

tailall方法比较类似, 都是注册到事件组合上。不同在于,指定事件都触发之后,如果事件依旧持续触发,将会在每次触发时调用handler,像一条尾巴一样。

基本事件

通过事件实现异步协作是EventProxy的主要亮点。除此之外,它还是一个基本的事件库。携带如下基本API

  • on/addListener 绑定事件监听器
  • emit 触发事件
  • once 绑定只执行一次的事件监听器
  • removeListener 移除事件监听器
  • removeAllListeners 移除单个事件或所有事件的监听器

异常处理

在异步方法中,实际上,异常处理需要占用一定比例的经历。在过去一段时间内,我们都是通过额外添加error事件来进行处理的,代码大致如下:

  1. exports.getContent = function(callback){
  2. var ep = new EventProxy();
  3. ep.all('tpl', 'data', function(tpl, data){
  4. //成功回调
  5. callback(null, {
  6. template: tpl,
  7. data: data
  8. });
  9. });
  10. //监听error事件
  11. ep.bind('error', function(err){
  12. //卸掉所有的handler
  13. ep.unbind();
  14. //异常回调
  15. callback(err);
  16. });
  17. fs.readFile('template.tpl', 'utf-8', function(err, content){
  18. if(err){
  19. //一旦异常发生,一律交给error事件的handler处理
  20. return ep.emit('error', err);
  21. }
  22. ep.emit('tpl', content);
  23. });
  24. db.get('sql', function(err, result){
  25. if(err){
  26. //一旦异常发生,一律交给error事件的handler处理
  27. return ep.emit('error', err);
  28. }
  29. ep.emit('data', result);
  30. });
  31. };

代码量因为异常的处理,一下子上去了很多。在这里EventProxy经过很多实践后,给我们提供了优化了的错误处理方案。

  1. exports.getContent = function(callback){
  2. var ep = new EventProxy();
  3. ep.all('tpl', 'data', function(tpl, data){
  4. //成功回调
  5. callback(null, {
  6. template: tpl,
  7. data: data
  8. });
  9. });
  10. //添加error handler
  11. ep.fail(callback);
  12. fs.readFile('template.tpl', 'utf-8', ep.done('tpl'));
  13. db.get('sql', ep.done('data'));
  14. };

上述代码优化之后,代码量明显降低。下面让我们来讨论一下faildone方法。

fail方法

  1. ep.fail(callback);
  2. //实际上为
  3. ep.fail(function(err){
  4. callback(err);
  5. });
  6. //等价于
  7. ep.bind('error', function(err){
  8. //卸载掉所有handler
  9. ep.unbind();
  10. //异常回调
  11. callback(err);
  12. });

fail方法监听了error事件,默认处理卸掉所有handler,并调用回调函数。

throw方法

throwep.emit('error', err)的简写。

  1. var err = new Error();
  2. ep.throw(err);
  3. //实际上
  4. ep.emit('error', err);

done方法

  1. ep.done('tpl');
  2. //等价于
  3. function(err, content){
  4. if(err){
  5. //一旦异常发生,一律交给error事件的handler处理
  6. return ep.emit('error', err);
  7. }
  8. ep.emit('tpl', content);
  9. }

在Node的最佳实践中,回调函数第一个参数一定是一个error对象。检测到异常后,将会触发error事件。剩下的参数,将触发事件,传递给对应handler处理。

done方法也接受回调函数

done方法除了接受事件名外,还接受回调函数。如果是函数时,它将剔除第一个error对象(此时应为null),后剩余的参数,传递给该回调函数作为参数。该回调函数无需要考虑异常处理。

  1. ep.done(function(content){
  2. //这里无需考虑异常
  3. //手动emit
  4. ep.emit('event', content);
  5. });

group

fail除了用于协助all方法完成外,也能协助after中的异常处理。另外在after的回调函数中,结果顺序是与用户emit的顺序有关。为了满足返回数据按发起异步调用的顺序排列,EventProxy提供了group方法。

  1. var ep = new EventProxy();
  2. ep.after('got_file', files.length, function(list){
  3. //在所有文件的异步执行结束后被执行
  4. //所有文件的内容都存在list数组中,按顺序排列
  5. });
  6. for(var i = 0; i < files.length; i++){
  7. fs.readFile(files[i], 'utf-8', ep.group('got_file'));
  8. }

group秉承done函数的设计,它包含异常的传递。同时它还隐含了对返回数据进行编号,在结束时,按顺序返回。

  1. ep.group('got_file');
  2. //约等价于
  3. function(err, data){
  4. if(err){
  5. return ep.emit('error', err);
  6. }
  7. ep.emit('got_file', data);
  8. };

当回调函数的数据还需要进行加工时,可以给group带上回调函数,只要在操作后将数据返回即可:

  1. ep.group('got_file', function(data){
  2. return data;
  3. });

注意事项

  • 请勿使用all作为业务的事件名。该事件名为保留事件。
  • 异常处理部分,请遵循Node的最佳实践(回调函数首个参数为异常传递位)。

上述内容为学习笔记,选自https://github.com/JacksonTian/eventproxy

欢迎转载,转载请注明出处

update by 2017/7/25 15:02

该部分完结

by 一枝猪

Node.js之eventproxy详解的更多相关文章

  1. 《Node.js开发实战详解》学习笔记

    <Node.js开发实战详解>学习笔记 ——持续更新中 一.NodeJS设计模式 1 . 单例模式 顾名思义,单例就是保证一个类只有一个实例,实现的方法是,先判断实例是否存在,如果存在则直 ...

  2. node.js的npm详解

    一.什么是npm呢 npm(Node Package Manager,node包管理器)是node的包管理器,他允许开发人员在node.js应用程序中创建,共享并重用模块.模块就是可以在不同的项目中重 ...

  3. Node.js HTTP 使用详解

    对于初学者有没有发觉在查看Node.js官方API的时候非常简单,只有几个洋文描述两下子,没了,我第一次一口气看完所以API后,对于第一个示例都有些懵,特别是参数里的request和response, ...

  4. Node.js中Async详解:流程控制

    安装 npm install async --save 地址 https://github.com/caolan/async Async的内容主要分为三部分 流程控制: 简化九种常见的流程的处理 集合 ...

  5. Node.js + Express中间件详解

    使用中间件 Express是一种路由和中间件Web框架,它具有自己的最小功能:Express应用程序本质上是一系列中间件函数调用. 中间件函数是可以访问请求对象 (req),响应对象(res)以及应用 ...

  6. 阿里云ECS服务器部署Node.js项目全过程详解

    本文详细介绍如何部署NodeJS项目到阿里云ECS上,以及本人在部署过程中所遇到的问题.坑点和解决办法,可以说是全网最全最详细的教程了.同时讲解了如何申请阿里云免费SSL证书,以及一台ECS服务器配置 ...

  7. ES6,ES2105核心功能一览,js新特性详解

    ES6,ES2105核心功能一览,js新特性详解 过去几年 JavaScript 发生了很大的变化.ES6(ECMAScript 6.ES2105)是 JavaScript 语言的新标准,2015 年 ...

  8. Js apply 方法 详解

    Js apply方法详解 我在一开始看到JavaScript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这 ...

  9. Js apply()使用详解

    Js apply方法详解 我在一开始看到javascript的函数apply和call时,非常的模糊,看也看不懂,最近在网上看到一些文章对apply方法和call的一些示例,总算是看的有点眉目了,在这 ...

随机推荐

  1. gitlab 实现自动部署(简单Python实现)

    功能说明: 当本地master分支执行push动作的时候,服务器端会自动执行master分支的pull操作(还可以执行一些自动化脚本) 原理: git hooks就是那些在git执行特定事件(如com ...

  2. IntelliJ IDEA(2017.2)安装和破解(转)

    如果有一定的经济基础,请支持正版,这里提供破解方法. 一.下载并安装, IntelliJ IDEA的官网:https://www.jetbrains.com 二.破解. 百度下载一个 Jetbrain ...

  3. 自适应Simpson积分

    自适应Simpson积分 作用 如标题所示,这玩意就是当你不会微积分的时候来求积分的. 总所周知,积分的定义就是函数的某一段与坐标轴之间的面积. 那么,自适应Simpson积分就是一种可以再某些精度下 ...

  4. HTML中直接写js 函数

    1.在HTML中直接写JS函数: <body onload="javascript:{window.location.href='http://www.baidu.com/'}&quo ...

  5. C/C++ 知识点---设计模式

    在软件工程中,设计模式用来描述在各种不同情况下,要怎么解决问题的一种方案.面向对象设计模式通常以类或对象来描述其中的关系和相互作用,是软件“设计”层次上的问题.使用设计模式可提高代码的重用性和可靠性, ...

  6. Eclipse快捷键:同时显示两个一模一样的代码窗口

    如图: 同样的一个HTML文件,在代码编辑窗口,显示两个.   快捷键: Ctrl + Shift + -(减号)   既可以展示两个,也可以只显示一个 附加一个快捷键: Ctrl + Shift + ...

  7. JMeter元件的作用域和执行顺序

    元件的作用域 配置元件:会影响其作用范围内的所有元件,作用范围是最大的,只要创建就对所有元件起作用. 前置处理器:在其作用范围内的每一个Sample元件之前执行: 定时器:对其作用范围内的每一个Sam ...

  8. Command "python setup.py egg_info" failed with error code 1一种问题的解决方法

    问题描述:无论是你在pycharm中直接使用import and install命令,还是pip的时候出现了Command "python setup.py egg_info" f ...

  9. noip提高组2011 Mayan游戏

    Mayan游戏 描述 Mayan puzzle是最近流行起来的一个游戏.游戏界面是一个7行5列的棋盘,上面堆放着一些方块,方块不能悬空堆放,即方块必须放在最下面一行,或者放在其他方块之上.**游戏通关 ...

  10. .NET平台微服务项目汇集

    最近博客园出现了一篇文章<微服务时代之2017年五军之战:Net PHP谁先死>,掀起了一波撕逼,作者只是从一个使用者的角度来指点江山,这个姿势是不对的..NET Core就是专门针对模块 ...