摘要:事件的監聽與事件的觸發事件一事件機制的實現中大部分的模塊,都繼承自模塊。從另一個角度來看,事件偵聽器模式也是一種事件鉤子的機制,利用事件鉤子導出內部數據或狀態給外部調用者。的核心就是事件發射與事件監聽器功能的封裝。
nodejs事件的監聽與事件的觸發
nodejs事件(Events)
一、事件機制的實現
Node.js中大部分的模塊,都繼承自Event模塊(http://nodejs.org/docs/latest... )。Event模塊(events.EventEmitter)是一個簡單的事件監聽器模式的實現。具有addListener/on,once,removeListener,removeAllListeners,emit等基本的事件監聽模式的方法實現。它與前端DOM樹上的事件并不相同,因為它不存在冒泡,逐層捕獲等屬于DOM的事件行為,也沒有preventDefault()、stopPropagation()、 stopImmediatePropagation() 等處理事件傳遞的方法。
從另一個角度來看,事件偵聽器模式也是一種事件鉤子(hook)的機制,利用事件鉤子導出內部數據或狀態給外部調用者。Node.js中的很多對象,大多具有黑盒的特點,功能點較少,如果不通過事件鉤子的形式,對象運行期間的中間值或內部狀態,是我們無法獲取到的。這種通過事件鉤子的方式,可以使編程者不用關注組件是如何啟動和執行的,只需關注在需要的事件點上即可。
二、事件觸發
events 模塊只提供了一個對象: events.EventEmitter。EventEmitter的核心就是事件發射與事件監聽器功能的封裝。EventEmitter的每個事件由一個事件名和若干個參數組成,事件名是一個字符串,通常表達一定的語義。對于每個事件,EventEmitter支持若干個事件監聽器。當事件發射時,注冊到這個事件的事件監聽器被依次調用,事件參數作為回調函數參數傳遞。
讓我們以下面的例子解釋這個過程:
//引入事件模塊 var events = require("events"); //創建事件監聽的一個對象 var emitter = new events.EventEmitter(); //監聽事件some_event emitter.addListener("some_event",function(){ console.log("事件觸發,調用此回調函數"); }); //觸發事件some_event emitter.emit("some_event");
運行結果:事件觸發,調用此回調函數
例子:
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", "byvoid", 1991);
運行的結果是:
listener1 byvoid 1991
listener2 byvoid 1991
以上例子中,emitter 為事件 someEvent 注冊了兩個事件監聽器,然后發射了someEvent事件。運行結果中可以看到兩個事件監聽器回調函數被先后調用。這就是EventEmitter最簡單的用法。接下來我們介紹一下EventEmitter常用的API。
EventEmitter.on(event, listener) 為指定事件注冊一個監聽器,接受一個字符串 event 和一個回調函數listener。EventEmitter.emit(event, [arg1], [arg2], [...]) 發射 event事件,傳遞若干可選參數到事件監聽器的參數表。
EventEmitter.once(event, listener) 為指定事件注冊一個單次監聽器,即監聽器最多只會觸發一次,觸發后立刻解除該監聽器。
EventEmitter.removeListener(event, listener) 移除指定事件的某個監聽器,listener 必須是該事件已經注冊過的監聽器。
EventEmitter.removeAllListeners([event]) 移除所有事件的所有監聽器,如果指定 event,則移除指定事件的所有監聽器。
更詳細的 API 文檔參見 http://nodejs.org/api/events....。
想想其實跟jquery自定義事件很相似:
//給element綁定hello事件 element.on("hello",function(){ alert("hello world!"); }); //觸發hello事件 element.trigger("hello");
三、事件機制的進階應用
繼承event.EventEmitter
實現一個繼承了EventEmitter類是十分簡單的,以下是Node.js中流對象繼承EventEmitter的例子:
var util = require("util"); var events = require("events"); //創建構造事件對象的構造函數 function Stream(){ events.EventEmitter.call(this); } util.inherits(Stream, events.EventEmitter); //實例創建事件監聽的一個對象 var elem = new Stream(); //監聽事件 elem.addListener("one_event",function(){ console.log("事件觸發,調用此回調函數"); }); //觸發事件some_event elem.emit("one_event");
值得一提的是如果對一個事件添加了超過10個偵聽器,將會得到一條警告,這一處設計與Node.js自身單線程運行有關,設計者認為偵聽器太多,可能導致內存泄漏,所以存在這樣一個警告。
實例:
var util = require("util"); var events = require("events"); function Stream(){ events.EventEmitter.call(this); } util.inherits(Stream, events.EventEmitter); var elem = new Stream(); elem.addListener("我來了",function(arg1,arg2){ console.log("事件觸發,調用此回調函數",arg1,arg2,1); }); elem.addListener("我來了",function(arg1,arg2){ console.log("事件觸發,調用此回調函數",arg1,arg2,2); }); elem.addListener("我來了",function(arg1,arg2){ console.log("事件觸發,調用此回調函數",arg1,arg2,3); }); elem.addListener("我來了",function(arg1,arg2){ console.log("事件觸發,調用此回調函數",arg1,arg2,4); }); elem.addListener("我來了",function(arg1,arg2){ console.log("事件觸發,調用此回調函數",arg1,arg2,5); }); elem.addListener("我來了",function(arg1,arg2){ console.log("事件觸發,調用此回調函數",arg1,arg2,6); }); elem.addListener("我來了",function(arg1,arg2){ console.log("事件觸發,調用此回調函數",arg1,arg2,7); }); elem.addListener("我來了",function(arg1,arg2){ console.log("事件觸發,調用此回調函數",arg1,arg2,8); }); elem.addListener("我來了",function(arg1,arg2){ console.log("事件觸發,調用此回調函數",arg1,arg2,9); }); elem.addListener("我來了",function(arg1,arg2){ console.log("事件觸發,調用此回調函數",arg1,arg2,10); }); elem.addListener("我來了",function(arg1,arg2){ console.log("事件觸發,調用此回調函數",arg1,arg2,11); }); //觸發事件some_event elem.emit("我來了","one","two");
我們通過調用emitter.setMaxListeners(0),就可以去帶哦限制
emitter.setMaxListeners(0);
一個經典的事件監聽觸發,進程通信例子:
master.js
var childprocess = require("child_process"); var worker = childprocess.fork("./worker.js"); console.log("pid in master:", process.pid); //監聽事件 worker.on("message", function(msg) { console.log("1:", msg); }) process.on("message", function(msg) { console.log("2:", msg); }) worker.send("---"); //觸發事件 message process.emit("message", "------");
worker.js
console.log("pid in worker:", process.pid); process.on("message", function(msg) { console.log("3:", msg); }); process.send("==="); process.emit("message", "======");
運行結果:
$ node master.js pid in master: 22229 // 主進程創建后打印其 pid 2: ------ // 主進程收到給自己發的消息 pid in worker: 22230 // 子進程創建后打印其 pid 3: ====== // 子進程收到給自己發的消息 1: === // 主進程收到來自子進程的消息 3: --- // 子進程收到來自主進程的消息
其中有兩個有趣的點:
在主進程中,使用 worker.on("message", ...) 監聽來自子進程的消息,使用 process.on("message", ...) 監聽給自己發的消息。但是在子進程中,只有 process.on("message", ...) 一種消息監聽方式,無法區分消息來源。
如果有給自己發消息的情況,則必須將對應的消息監聽的代碼放在消息發送代碼前面,否則無法監聽到該消息發送。例如將 master.js 的最后一行代碼 process.emit("message", "------"); 放置到該文件第一行,則運行結果不會輸出 2: ------。
如果不能控制消息監聽代碼和消息發送代碼的先后順序,可將給自己發送消息的代碼改寫為 setImmediate(process.emit.bind(process, "message", {{message}}));
參考資料:
http://www.cnblogs.com/zhongw...(很多實例)
http://www.infoq.com/cn/artic...
http://www.toolmao.com/nodejs...
http://www.ynpxrz.com/n691854...
http://www.jb51.net/article/6...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/90396.html
摘要:因為進程退出之后將不再執行事件循環,所有只有那些沒有回調函數的代碼才會被執行。此外,創建的回調函數具有隔離性,他們之間不會相互影響。我們來看的一個簡單例子,他創建了一個子進程,第一個參數是一個命令,第二個參數是回調函數,處理返回結果。 雖然node對操作系統做了很多抽象的工作,但是你還是可以直接和他交互,比如和系統中已經存在的進程進行交互,創建工作子進程。node是一個用于事件循環的線...
摘要:否則,繼續判斷頭節點是否是的實例,是一個紅黑樹,若是,則直接在樹中插入。在中有一個屬性為,這是一個閾值,若數量超過它,鏈表會轉化為紅黑樹,小于它則會換回鏈表。所以同時用到了數組,鏈表,紅黑樹這三種數據結構。 1. HashMap中Node類: static class Node implements Map.Entry { final int hash; ...
摘要:是一個全局內置對象,可以在代碼中的任何位置訪問此對象,這個對象代表我們的代碼宿主的操作系統進程對象。使用對象可以截獲進程的異常退出等事件,也可以獲取進程的當前目錄環境變量內存占用等信息,還可以執行進程退出工作目錄切換等操作。 process是一個全局內置對象,可以在代碼中的任何位置訪問此對象,這個對象代表我們的node.js代碼宿主的操作系統進程對象。使用process對象可以截獲進程...
閱讀 1831·2021-09-28 09:46
閱讀 3150·2019-08-30 14:22
閱讀 1883·2019-08-26 13:36
閱讀 3350·2019-08-26 11:32
閱讀 2099·2019-08-23 16:56
閱讀 1154·2019-08-23 16:09
閱讀 1308·2019-08-23 12:55
閱讀 2155·2019-08-23 11:44