您好,登錄后才能下訂單哦!
使用node實現事件循環?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
事件循環
Node.js 是單進程單線程應用程序,但是因為 V8 引擎提供的異步執行回調接口,通過這些接口可以處理大量的并發,所以性能非常高。
Node.js 幾乎每一個 API 都是支持回調函數的。
Node.js 基本上所有的事件機制都是用設計模式中觀察者模式實現。
Node.js 單線程類似進入一個while(true)的事件循環,直到沒有事件觀察者退出,每個異步事件都生成一個事件觀察者,如果有事件發生就調用該回調函數.
進程:CPU執行任務的模塊
線程:模塊中的最小單元
舉個通俗的例子:
cpu比作我們每個人,到飯點吃飯了。可以點很多菜(cpu中的進程):宮保雞丁,魚香肉絲,酸辣土豆絲。每樣菜具體包含了哪些內容(cpu每個進程中的線程):宮保雞丁(詳情:黃瓜、胡蘿卜、雞肉、花生米)。而詳情構成了宮保雞丁這道菜,吃了以后不餓。就可以干活了,cpu中的進程里的線程也是同理。當線程完成自己的內容將結果返回給進程,進程返回給cpu的時候。cpu就能處理日常需求。
事件驅動程序
Node.js使用事件驅動模型,當web server接收到請求,就把它關閉然后進行處理,然后去服務下一個web請求
當這個請求完成,它被放回處理隊列,當到達隊列開頭,這個結果就返回給用戶。
這個模型非常高效可擴展性非常強,因為 webserver 一直接受請求而不等待任何讀寫操作。(這也稱之為非阻塞式IO或者事件驅動IO)
在事件驅動模型中,會生成一個主循環來監聽事件,當檢測到事件時觸發回調函數。
整個事件驅動的流程就是這么實現的,非常簡潔。有點類似于觀察者模式,事件相當于一個主題(Subject),而所有注冊到這個事件上的處理函數相當于觀察者(Observer)。
Node.js 有多個內置的事件,我們可以通過引入 events 模塊,并通過實例化 EventEmitter 類來綁定和監聽事件,如下實例:
// 引入events模塊 let events = require('events'); //創建eventEmitter對象 let eventEmitter = new events.EventEmitter(); //綁定事件以及事件處理程序 eventEmitter.on('eventName',eventHandler); //通過程序觸發事件 eventEmitter.emit('eventName')
示例:
//引入events模塊 let events = require('events'); //創建eventEmitter對象 let eventEmitter = new events.EventEmitter(); //創建事件處理程序 let connectHandle = function connected() { console.log('連接成功'); //觸發data_received事件 eventEmitter.emit('data_received') } //綁定connection事件處理程序 eventEmitter.on('connection', connectHandle); //使用匿名函數綁定data_received事件 eventEmitter.on('data_received', function () { console.log('數據接收成功'); }) //觸發connecttion事件 eventEmitter.emit('connection'); console.log('程序執行完畢'); // 執行結果: // 連接成功 // 數據接收成功 // 程序執行完畢
eventEmitter.emit 是觸發事件(事件請求),eventEmitter.on是綁定處理事件的處理器(事件處理),事件的請求和處理是分開的,所以是異步。
EventEmitter
node.js所有的異步I/O操作在完成時都會發送一個事件到事件隊列
node.js里面的許多對象都會分發事件:一個net.Server對象會在每次有新連接時觸發的一個事件,一個fs.readStream對象會在文件被打開的時候觸發一個事件。所有這些產生事件的對象都是events.EventEmitter的實例
events 模塊只提供了一個對象: events.EventEmitter。EventEmitter 的核心就是事件觸發與事件監聽器功能的封裝。
EventEmitter 對象如果在實例化時發生錯誤,會觸發 error 事件。當添加新的監聽器時,newListener 事件會觸發,當監聽器被移除時,removeListener 事件被觸發。
簡單用法
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);
運行這段代碼,1 秒后控制臺輸出了 ‘some_event 事件觸發'。
其原理是 event 對象注冊了事件 some_event 的一個監聽器,
然后我們通過 setTimeout 在 1000 毫秒以后向 event 對象發送事件 some_event,此時會調用some_event 的監聽器。
EventEmitter 的每個事件由一個事件名和若干個參數組成,事件名是一個字符串,通常表達一定的語義。對于每個事件,EventEmitter 支持 若干個事件監聽器。
當事件觸發時,注冊到這個事件的事件監聽器被依次調用,事件參數作為回調函數參數傳遞。
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 參數'); //輸出: // listener1 arg1 參數 arg2 參數 // listener2 arg1 參數 arg2 參數
以上例子中,emitter 為事件 someEvent 注冊了兩個事件監聽器,然后觸發了 someEvent 事件。
運行結果中可以看到兩個事件監聽器回調函數被先后調用。 這就是EventEmitter最簡單的用法。
EventEmitter 提供了多個屬性,如 on 和 emit。on 函數用于綁定事件函數,emit 屬性用于觸發一個事件。、
EventEmitter屬性
測試
/* * @Author: angula * @Date: 2020-09-21 22:29:18 * @LastEditTime: 2020-09-22 11:27:56 * @FilePath: \JS\Github-前端知識總結倉庫\studySummary\Node.js學習筆記\事件循環\index2.js */ let events = require('events'); let eventEmitter = new events.EventEmitter(); // 監聽器1 let listener1 = function listener1() { console.log('監聽器listener1啟動。。。'); } // 監聽器2 let listener2 = function listener2() { console.log('監聽器listener2啟動。。。'); } // 綁定connection事件,處理函數為listener1 eventEmitter.addListener('connection', listener1); // 綁定connection事件,處理函數為listener2 eventEmitter.on('connection', listener2); //類,返回監聽器的數量 let eventListeners = eventEmitter.listenerCount('connection'); console.log(eventListeners + '個監聽器監聽連接事件。'); //處理connection事件 eventEmitter.emit('connection'); // 移除綁定的listener1 eventEmitter.removeListener('connection', listener1); console.log('listener1不再受監聽'); //觸發連接事件 eventEmitter.emit('connection'); eventListeners = eventEmitter.listenerCount('connection'); console.log(eventListeners + '個監聽器連接事件'); console.log('程序執行完畢');
執行結果:
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。