国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Node事件機(jī)制小記

airborne007 / 890人閱讀

摘要:事件的監(jiān)聽與事件的觸發(fā)事件一事件機(jī)制的實(shí)現(xiàn)中大部分的模塊,都繼承自模塊。從另一個(gè)角度來看,事件偵聽器模式也是一種事件鉤子的機(jī)制,利用事件鉤子導(dǎo)出內(nèi)部數(shù)據(jù)或狀態(tài)給外部調(diào)用者。的核心就是事件發(fā)射與事件監(jiān)聽器功能的封裝。

nodejs事件的監(jiān)聽與事件的觸發(fā)

nodejs事件(Events)

一、事件機(jī)制的實(shí)現(xiàn)

Node.js中大部分的模塊,都繼承自Event模塊(http://nodejs.org/docs/latest... )。Event模塊(events.EventEmitter)是一個(gè)簡(jiǎn)單的事件監(jiān)聽器模式的實(shí)現(xiàn)。具有addListener/on,once,removeListener,removeAllListeners,emit等基本的事件監(jiān)聽模式的方法實(shí)現(xiàn)。它與前端DOM樹上的事件并不相同,因?yàn)樗淮嬖诿芭荩饘硬东@等屬于DOM的事件行為,也沒有preventDefault()、stopPropagation()、 stopImmediatePropagation() 等處理事件傳遞的方法。
從另一個(gè)角度來看,事件偵聽器模式也是一種事件鉤子(hook)的機(jī)制,利用事件鉤子導(dǎo)出內(nèi)部數(shù)據(jù)或狀態(tài)給外部調(diào)用者。Node.js中的很多對(duì)象,大多具有黑盒的特點(diǎn),功能點(diǎn)較少,如果不通過事件鉤子的形式,對(duì)象運(yùn)行期間的中間值或內(nèi)部狀態(tài),是我們無法獲取到的。這種通過事件鉤子的方式,可以使編程者不用關(guān)注組件是如何啟動(dòng)和執(zhí)行的,只需關(guān)注在需要的事件點(diǎn)上即可。

二、事件觸發(fā)

events 模塊只提供了一個(gè)對(duì)象: events.EventEmitter。EventEmitter的核心就是事件發(fā)射與事件監(jiān)聽器功能的封裝。EventEmitter的每個(gè)事件由一個(gè)事件名和若干個(gè)參數(shù)組成,事件名是一個(gè)字符串,通常表達(dá)一定的語義。對(duì)于每個(gè)事件,EventEmitter支持若干個(gè)事件監(jiān)聽器。當(dāng)事件發(fā)射時(shí),注冊(cè)到這個(gè)事件的事件監(jiān)聽器被依次調(diào)用,事件參數(shù)作為回調(diào)函數(shù)參數(shù)傳遞。

  讓我們以下面的例子解釋這個(gè)過程:

//引入事件模塊
var events = require("events");

//創(chuàng)建事件監(jiān)聽的一個(gè)對(duì)象
var  emitter = new events.EventEmitter();

//監(jiān)聽事件some_event
emitter.addListener("some_event",function(){
    console.log("事件觸發(fā),調(diào)用此回調(diào)函數(shù)");
});

//觸發(fā)事件some_event
emitter.emit("some_event");

 運(yùn)行結(jié)果:事件觸發(fā),調(diào)用此回調(diào)函數(shù)

 例子:

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);

 運(yùn)行的結(jié)果是:

  listener1 byvoid 1991

  listener2 byvoid 1991

  以上例子中,emitter 為事件 someEvent 注冊(cè)了兩個(gè)事件監(jiān)聽器,然后發(fā)射了someEvent事件。運(yùn)行結(jié)果中可以看到兩個(gè)事件監(jiān)聽器回調(diào)函數(shù)被先后調(diào)用。這就是EventEmitter最簡(jiǎn)單的用法。接下來我們介紹一下EventEmitter常用的API。
   EventEmitter.on(event, listener) 為指定事件注冊(cè)一個(gè)監(jiān)聽器,接受一個(gè)字符串 event 和一個(gè)回調(diào)函數(shù)listener。EventEmitter.emit(event, [arg1], [arg2], [...]) 發(fā)射 event事件,傳遞若干可選參數(shù)到事件監(jiān)聽器的參數(shù)表。
  EventEmitter.once(event, listener) 為指定事件注冊(cè)一個(gè)單次監(jiān)聽器,即監(jiān)聽器最多只會(huì)觸發(fā)一次,觸發(fā)后立刻解除該監(jiān)聽器。
  EventEmitter.removeListener(event, listener) 移除指定事件的某個(gè)監(jiān)聽器,listener 必須是該事件已經(jīng)注冊(cè)過的監(jiān)聽器。
  EventEmitter.removeAllListeners([event]) 移除所有事件的所有監(jiān)聽器,如果指定 event,則移除指定事件的所有監(jiān)聽器。
  更詳細(xì)的 API 文檔參見 http://nodejs.org/api/events....。

 想想其實(shí)跟jquery自定義事件很相似:

//給element綁定hello事件
element.on("hello",function(){
  alert("hello world!");
});
//觸發(fā)hello事件
element.trigger("hello");

三、事件機(jī)制的進(jìn)階應(yīng)用

繼承event.EventEmitter

實(shí)現(xiàn)一個(gè)繼承了EventEmitter類是十分簡(jiǎn)單的,以下是Node.js中流對(duì)象繼承EventEmitter的例子:

var util = require("util");

var events = require("events");

//創(chuàng)建構(gòu)造事件對(duì)象的構(gòu)造函數(shù)
function Stream(){
    events.EventEmitter.call(this);
}
util.inherits(Stream, events.EventEmitter);

//實(shí)例創(chuàng)建事件監(jiān)聽的一個(gè)對(duì)象
var elem = new Stream();

//監(jiān)聽事件
elem.addListener("one_event",function(){
    console.log("事件觸發(fā),調(diào)用此回調(diào)函數(shù)");
});

//觸發(fā)事件some_event
elem.emit("one_event");

值得一提的是如果對(duì)一個(gè)事件添加了超過10個(gè)偵聽器,將會(huì)得到一條警告,這一處設(shè)計(jì)與Node.js自身單線程運(yùn)行有關(guān),設(shè)計(jì)者認(rèn)為偵聽器太多,可能導(dǎo)致內(nèi)存泄漏,所以存在這樣一個(gè)警告。

實(shí)例:

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("事件觸發(fā),調(diào)用此回調(diào)函數(shù)",arg1,arg2,1);
});

elem.addListener("我來了",function(arg1,arg2){
    console.log("事件觸發(fā),調(diào)用此回調(diào)函數(shù)",arg1,arg2,2);
});

elem.addListener("我來了",function(arg1,arg2){
    console.log("事件觸發(fā),調(diào)用此回調(diào)函數(shù)",arg1,arg2,3);
});

elem.addListener("我來了",function(arg1,arg2){
    console.log("事件觸發(fā),調(diào)用此回調(diào)函數(shù)",arg1,arg2,4);
});

elem.addListener("我來了",function(arg1,arg2){
    console.log("事件觸發(fā),調(diào)用此回調(diào)函數(shù)",arg1,arg2,5);
});

elem.addListener("我來了",function(arg1,arg2){
    console.log("事件觸發(fā),調(diào)用此回調(diào)函數(shù)",arg1,arg2,6);
});

elem.addListener("我來了",function(arg1,arg2){
    console.log("事件觸發(fā),調(diào)用此回調(diào)函數(shù)",arg1,arg2,7);
});

elem.addListener("我來了",function(arg1,arg2){
    console.log("事件觸發(fā),調(diào)用此回調(diào)函數(shù)",arg1,arg2,8);
});

elem.addListener("我來了",function(arg1,arg2){
    console.log("事件觸發(fā),調(diào)用此回調(diào)函數(shù)",arg1,arg2,9);
});

elem.addListener("我來了",function(arg1,arg2){
    console.log("事件觸發(fā),調(diào)用此回調(diào)函數(shù)",arg1,arg2,10);
});
elem.addListener("我來了",function(arg1,arg2){
    console.log("事件觸發(fā),調(diào)用此回調(diào)函數(shù)",arg1,arg2,11);
});
//觸發(fā)事件some_event
elem.emit("我來了","one","two");

我們通過調(diào)用emitter.setMaxListeners(0),就可以去帶哦限制

emitter.setMaxListeners(0);

一個(gè)經(jīng)典的事件監(jiān)聽觸發(fā),進(jìn)程通信例子:
master.js 

var childprocess = require("child_process");
var worker = childprocess.fork("./worker.js");

console.log("pid in master:", process.pid);

//監(jiān)聽事件
worker.on("message", function(msg) {
  console.log("1:", msg);
})
process.on("message", function(msg) {
  console.log("2:", msg);
})

worker.send("---");

//觸發(fā)事件 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", "======");

  運(yùn)行結(jié)果:

$ node master.js


pid in master: 22229      // 主進(jìn)程創(chuàng)建后打印其 pid
2: ------                 // 主進(jìn)程收到給自己發(fā)的消息
pid in worker: 22230      // 子進(jìn)程創(chuàng)建后打印其 pid
3: ======                 // 子進(jìn)程收到給自己發(fā)的消息 
1: ===                    // 主進(jìn)程收到來自子進(jìn)程的消息
3: ---                    // 子進(jìn)程收到來自主進(jìn)程的消息

其中有兩個(gè)有趣的點(diǎn):

  在主進(jìn)程中,使用 worker.on("message", ...) 監(jiān)聽來自子進(jìn)程的消息,使用 process.on("message", ...) 監(jiān)聽給自己發(fā)的消息。但是在子進(jìn)程中,只有 process.on("message", ...) 一種消息監(jiān)聽方式,無法區(qū)分消息來源。

如果有給自己發(fā)消息的情況,則必須將對(duì)應(yīng)的消息監(jiān)聽的代碼放在消息發(fā)送代碼前面,否則無法監(jiān)聽到該消息發(fā)送。例如將 master.js 的最后一行代碼 process.emit("message", "------"); 放置到該文件第一行,則運(yùn)行結(jié)果不會(huì)輸出 2: ------。

如果不能控制消息監(jiān)聽代碼和消息發(fā)送代碼的先后順序,可將給自己發(fā)送消息的代碼改寫為 setImmediate(process.emit.bind(process, "message", {{message}}));

  

 參考資料:

  http://www.cnblogs.com/zhongw...(很多實(shí)例)

  http://www.infoq.com/cn/artic...

  http://www.toolmao.com/nodejs...

  http://www.ynpxrz.com/n691854...

  http://www.jb51.net/article/6...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/90396.html

相關(guān)文章

  • nodejs之process進(jìn)程小記

    摘要:因?yàn)檫M(jìn)程退出之后將不再執(zhí)行事件循環(huán),所有只有那些沒有回調(diào)函數(shù)的代碼才會(huì)被執(zhí)行。此外,創(chuàng)建的回調(diào)函數(shù)具有隔離性,他們之間不會(huì)相互影響。我們來看的一個(gè)簡(jiǎn)單例子,他創(chuàng)建了一個(gè)子進(jìn)程,第一個(gè)參數(shù)是一個(gè)命令,第二個(gè)參數(shù)是回調(diào)函數(shù),處理返回結(jié)果。 雖然node對(duì)操作系統(tǒng)做了很多抽象的工作,但是你還是可以直接和他交互,比如和系統(tǒng)中已經(jīng)存在的進(jìn)程進(jìn)行交互,創(chuàng)建工作子進(jìn)程。node是一個(gè)用于事件循環(huán)的線...

    Binguner 評(píng)論0 收藏0
  • HashMap源碼閱讀小記

    摘要:否則,繼續(xù)判斷頭節(jié)點(diǎn)是否是的實(shí)例,是一個(gè)紅黑樹,若是,則直接在樹中插入。在中有一個(gè)屬性為,這是一個(gè)閾值,若數(shù)量超過它,鏈表會(huì)轉(zhuǎn)化為紅黑樹,小于它則會(huì)換回鏈表。所以同時(shí)用到了數(shù)組,鏈表,紅黑樹這三種數(shù)據(jù)結(jié)構(gòu)。 1. HashMap中Node類: static class Node implements Map.Entry { final int hash; ...

    blastz 評(píng)論0 收藏0
  • nadejs進(jìn)程管理小記

    摘要:是一個(gè)全局內(nèi)置對(duì)象,可以在代碼中的任何位置訪問此對(duì)象,這個(gè)對(duì)象代表我們的代碼宿主的操作系統(tǒng)進(jìn)程對(duì)象。使用對(duì)象可以截獲進(jìn)程的異常退出等事件,也可以獲取進(jìn)程的當(dāng)前目錄環(huán)境變量?jī)?nèi)存占用等信息,還可以執(zhí)行進(jìn)程退出工作目錄切換等操作。 process是一個(gè)全局內(nèi)置對(duì)象,可以在代碼中的任何位置訪問此對(duì)象,這個(gè)對(duì)象代表我們的node.js代碼宿主的操作系統(tǒng)進(jìn)程對(duì)象。使用process對(duì)象可以截獲進(jìn)程...

    dendoink 評(píng)論0 收藏0
  • h5喚醒APP小記

    摘要:比如聯(lián)系方式銀行卡信用卡信息支付寶各大商城的賬戶密碼照片甚至行程與位置信息等。針對(duì)這個(gè)問題,蘋果使用了名為沙盒的機(jī)制應(yīng)用只能訪問它聲明可能訪問的資源。 h5喚醒APP功能 最近遇到一個(gè)需求,需要在從APP分享出去的H5頁面中,帶有一個(gè)立即打開的按鈕,如果本地安裝了app,那么就直接喚起本地的app,如果沒有安裝,則跳轉(zhuǎn)到下載。這是一個(gè)很正常的推廣和導(dǎo)流量的策略。前端小白從來沒有做過這個(gè)...

    KnewOne 評(píng)論0 收藏0
  • h5喚醒APP小記

    摘要:比如聯(lián)系方式銀行卡信用卡信息支付寶各大商城的賬戶密碼照片甚至行程與位置信息等。針對(duì)這個(gè)問題,蘋果使用了名為沙盒的機(jī)制應(yīng)用只能訪問它聲明可能訪問的資源。 h5喚醒APP功能 最近遇到一個(gè)需求,需要在從APP分享出去的H5頁面中,帶有一個(gè)立即打開的按鈕,如果本地安裝了app,那么就直接喚起本地的app,如果沒有安裝,則跳轉(zhuǎn)到下載。這是一個(gè)很正常的推廣和導(dǎo)流量的策略。前端小白從來沒有做過這個(gè)...

    jayzou 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<