[Node.js] 04 - Event and Callback

回調函數

回調函數在完成任務後就會被調用,Node 使用了大量的回調函數,Node 全部 API 都支持回調函數。javascript

異步讀取文件的回調函數:java

var fs = require("fs");

fs.readFile('input.txt', function (err, data) { if (err) return console.error(err);
    console.log(data.toString());
});

console.log("程序執行結束!");

 

 

觀察者監視事件

Node.js 的每個 API 都是異步的node

Node.js 基本上全部的事件機制都是用設計模式中觀察者模式實現。設計模式

Node.js 單線程相似 進入一個while(true)的事件循環,直到沒有事件 觀察者退出,每一個異步事件都生成一個事件觀察者,若是有事件發生(觀察者)就調用該回調函數。異步

有點相似於觀察者模式,事件至關於一個主題(Subject),而全部註冊到這個事件上的處理函數至關於觀察者(Observer)函數

var events       = require('events');
var eventEmitter = new events.EventEmitter();
--------------------------------------------------------------------
// 方法1.採用handler函數
// 建立事件處理程序 var connectHandler = function connected() { console.log('鏈接成功');            // step 1 eventEmitter.emit('data_received');     // 這裏觸發 step 2 } // 綁定 connection 事件處理程序 eventEmitter.on('connection', connectHandler);
--------------------------------------------------------------------

// 方法2.採用匿名函數(或者箭頭函數)
// 使用匿名函數綁定 data_received 事件 eventEmitter.on('data_received', function(){ console.log('數據接收成功');          // step 2 }); // 觸發 connection 事件 eventEmitter.emit('connection');        // 這裏觸發 step 1 console.log("程序執行完畢。");       // step 3

 

 

多個觀察者

//event.js 文件
var events = require('events'); 
var emitter = new events.EventEmitter(); 
emitter.on(
'someEvent', function(arg1, arg2) { console.log('listener1', arg1, arg2); }); emitter.on('someEvent', function(arg1, arg2) { console.log('listener2', arg1, arg2); }); emitter.emit('someEvent', 'arg1 參數', 'arg2 參數');

當事件觸發時,註冊到這個事件的事件監聽器被依次調用,事件參數做爲回調函數參數傳遞。ui

$ node event.js 
listener1 arg1 參數 arg2 參數
listener2 arg1 參數 arg2 參數

 

 

延時觸發

//event.js 文件
var EventEmitter = require('events').EventEmitter; 
var event = new EventEmitter(); 
event.on('some_event', function() { 
    console.log('some_event 事件觸發'); 
}); 
setTimeout(
function() { event.emit('some_event'); }, 1000);

順便提一個:間隔觸發spa

setInterval ( ); --> clearInterval(timer); 線程

<script type="text/javascript"> 
window.onload = function () {
    var count = 0;
    var bt    = document.getElementById("bt");
    function show(){ 
        document.getElementById("ant").innerHTML = count + 1;
        count = count +1; 
    } 
    var flag   = setInterval(show, 1000);
    bt.onclick = function () {
        clearInterval(flag);
    }
} 
</script> 

  

一個綜合性的例子:設計

var events       = require('events');
var eventEmitter = new events.EventEmitter();

// (1) 定義監聽回調方法
// 監聽器 #1 var listener1 = function listener1() { console.log('監聽器 listener1 執行。'); } // 監聽器 #2 var listener2 = function listener2() { console.log('監聽器 listener2 執行。'); }
// (2) 兩種綁定監聽器到事件上
// 綁定 connection 事件,處理函數爲 listener1 eventEmitter.addListener('connection', listener1); // 綁定 connection 事件,處理函數爲 listener2 eventEmitter.on('connection', listener2);
var eventListeners = require('events').EventEmitter.listenerCount(eventEmitter,'connection'); console.log(eventListeners + " 個監聽器監聽鏈接事件。");
// (3) 觸發事件發生
// 處理 connection 事件 eventEmitter.emit('connection');
// (4) 去掉監聽器
// 移除監綁定的 listener1 函數 eventEmitter.removeListener('connection', listener1); console.log("listener1 再也不受監聽。"); // 觸發鏈接事件 eventEmitter.emit('connection'); eventListeners = require('events').EventEmitter.listenerCount(eventEmitter,'connection'); console.log(eventListeners + " 個監聽器監聽鏈接事件。"); console.log("程序執行完畢。");

 

 

Error 事件

EventEmitter 定義了一個特殊的事件 error,它包含了錯誤的語義,遇到 異常的時候一般會觸發 error 事件。

當 error 被觸發時,EventEmitter 規定若是沒有響 應的監聽器,Node.js 會把它看成異常,退出程序並輸出錯誤信息。

咱們通常要爲會觸發 error 事件的對象設置監聽器,避免遇到錯誤後整個程序崩潰。例如:

var events = require('events'); 
var emitter = new events.EventEmitter(); 
emitter.emit('error'); 

 

 

繼承 EventEmitter

大多數時候咱們不會直接使用 EventEmitter,而是在對象中繼承它。包括 fs、net、 http 在內的,只要是支持事件響應的核心模塊都是 EventEmitter 的子類。

爲何要這樣作呢?緣由有兩點:

  • 首先,具備某個實體功能的對象實現事件符合語義, 事件的監聽發生應該是一個對象的方法
  • 其次 JavaScript 的對象機制是基於原型的,支持 部分多重繼承,繼承 EventEmitter 不會打亂對象原有的繼承關係。

 

Person類自己會有多個有意義的對象,好比:xiaoming, lili, lucy。

但願他們對同一個事件都會有相似的反應,好比老師喊報名,各自起來報本身姓名。

故,這裏觸發事件speak綁定在每個person身上。

以後,觸發了xiaoming的神經;觸發了lucy的神經。

相關文章
相關標籤/搜索