安装git
npm install eventproxy --save
github
调用sql
var EventProxy = require('eventproxy');
数据库
此处以页面渲染为场景,渲染页面须要模版、数据。假设都须要异步读取。npm
var EventProxy = require('eventproxy'); //获取EventProxy实例 var ep = new EventProxy(); ep.all('tpl', 'data', function(tpl, data){//or ep.all(['tpl', 'data'], function(tpl, data{})) //在全部指定的事件触发后, 将会被调用执行 //参数对应各自的事件名 }); fs.readFile('template.tpl', 'utf-8', function(err, content){ ep.emit('tpl', content); }); db.get('sql', function(err, content){ ep.emit('data', result); });
all
方法将handler注册到事件组合上。当注册的全部事件均触发后,将会调用handler执行,每一个事件传递的数据,将会依照事件名顺序,传入handler做为参数。数组
EventProxy提供了create
静态方法,能够快速完成注册all事件。异步
var ep_create = EventProxy.create('tpl', 'data', function(tpl, data){ //TODO });
以上方法等效于函数
var ep = new EventProxy(); ep.all('tpl', 'data', function(tpl, data){ //TODO });
此处以读取目录下全部文件为例,在异步操做中,咱们须要在全部异步调用结束后,执行某些操做。学习
var ep = new EventProxy(); ep.after('got_file', files.length, function(list){ //在全部文件的异步执行结束后将被执行 //全部文件的内容都存在list数组中 }); for(var i = 0; i<files.length; i++){ fs.readFile(files[i], 'utf-8', function(err, content){ //触发结果事件 ep.emit('got_file', content); }) }
after
方法适合重复的操做,好比爬10个网站,读10个文件,调用5次数据库等。将handler注册到N次相同事件的触发上。达到指定的触发数,handler将会被调用执行,每次触发的数据,将会按触发顺序,存为数组做为参数传入。优化
此处以股票为例,数据和模版都是异步获取,可是数据会持续刷新,视图会须要从新刷新。
var ep = new EventProxy(); ep.tail('tpl', 'data', function(tpl, data){ //待全部指定的时间都触发后,将第一次回调 //之后再出发其中之一的时间,都会回调 }); fs.readFile('template.tpl', 'utf-8', function(err, content){ ep.emit('tpl', content); }); setInterval(function(){ db.get('sql', function(err, result){ ep.emit('data', result); }); }, 2000);
tail
与all
方法比较相似, 都是注册到事件组合上。不一样在于,指定事件都触发以后,若是事件依旧持续触发,将会在每次触发时调用handler,像一条尾巴同样。
经过事件实现异步协做是EventProxy的主要亮点。除此以外,它仍是一个基本的事件库。携带以下基本API
on/addListener
绑定事件监听器emit
触发事件once
绑定只执行一次的事件监听器removeListener
移除事件监听器removeAllListeners
移除单个事件或全部事件的监听器在异步方法中,实际上,异常处理须要占用必定比例的经历。在过去一段时间内,咱们都是经过额外添加error
事件来进行处理的,代码大体以下:
exports.getContent = function(callback){ var ep = new EventProxy(); ep.all('tpl', 'data', function(tpl, data){ //成功回调 callback(null, { template: tpl, data: data }); }); //监听error事件 ep.bind('error', function(err){ //卸掉全部的handler ep.unbind(); //异常回调 callback(err); }); fs.readFile('template.tpl', 'utf-8', function(err, content){ if(err){ //一旦异常发生,一概交给error事件的handler处理 return ep.emit('error', err); } ep.emit('tpl', content); }); db.get('sql', function(err, result){ if(err){ //一旦异常发生,一概交给error事件的handler处理 return ep.emit('error', err); } ep.emit('data', result); }); };
代码量由于异常的处理,一会儿上去了不少。在这里EventProxy通过不少实践后,给咱们提供了优化了的错误处理方案。
exports.getContent = function(callback){ var ep = new EventProxy(); ep.all('tpl', 'data', function(tpl, data){ //成功回调 callback(null, { template: tpl, data: data }); }); //添加error handler ep.fail(callback); fs.readFile('template.tpl', 'utf-8', ep.done('tpl')); db.get('sql', ep.done('data')); };
上述代码优化以后,代码量明显下降。下面让咱们来讨论一下fail
和done
方法。
ep.fail(callback); //实际上为 ep.fail(function(err){ callback(err); }); //等价于 ep.bind('error', function(err){ //卸载掉全部handler ep.unbind(); //异常回调 callback(err); });
fail
方法监听了error
事件,默认处理卸掉全部handler,并调用回调函数。
throw
是ep.emit('error', err)
的简写。
var err = new Error(); ep.throw(err); //实际上 ep.emit('error', err);
ep.done('tpl'); //等价于 function(err, content){ if(err){ //一旦异常发生,一概交给error事件的handler处理 return ep.emit('error', err); } ep.emit('tpl', content); }
在Node的最佳实践中,回调函数第一个参数必定是一个error
对象。检测到异常后,将会触发error
事件。剩下的参数,将触发事件,传递给对应handler处理。
done
方法除了接受事件名外,还接受回调函数。若是是函数时,它将剔除第一个error对象(此时应为null
),后剩余的参数,传递给该回调函数做为参数。该回调函数无须要考虑异常处理。
ep.done(function(content){ //这里无需考虑异常 //手动emit ep.emit('event', content); });
fail
除了用于协助all
方法完成外,也能协助after
中的异常处理。另外在after
的回调函数中,结果顺序是与用户emit
的顺序有关。为了知足返回数据按发起异步调用的顺序排列,EventProxy
提供了group
方法。
var ep = new EventProxy(); ep.after('got_file', files.length, function(list){ //在全部文件的异步执行结束后被执行 //全部文件的内容都存在list数组中,按顺序排列 }); for(var i = 0; i < files.length; i++){ fs.readFile(files[i], 'utf-8', ep.group('got_file')); }
group
秉承done
函数的设计,它包含异常的传递。同时它还隐含了对返回数据进行编号,在结束时,按顺序返回。
ep.group('got_file'); //约等价于 function(err, data){ if(err){ return ep.emit('error', err); } ep.emit('got_file', data); };
当回调函数的数据还须要进行加工时,能够给group
带上回调函数,只要在操做后将数据返回便可:
ep.group('got_file', function(data){ return data; });
all
做为业务的事件名。该事件名为保留事件。上述内容为学习笔记,选自https://github.com/JacksonTian/eventproxy
欢迎转载,转载请注明出处
update by 2017/7/25 15:02
该部分完结
by 一枝猪