安裝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 一枝豬