// 01.js const EventEmitter = require('events'); class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter(); myEmitter.on('event', () => { console.log('an event occurred!'); }); myEmitter.emit('event');
輸出:node
an event occurred!
emit()
方法能夠傳不限制數量的參數。// 02.js const EventEmitter = require('events') class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter() myEmitter.on('event', function (a, b){ console.log(a, b, this, this === myEmitter) }) myEmitter.on('event', (a, b) => { console.log(a, b, this, this === myEmitter) }) myEmitter.emit('event', 'a', {name:'wdd'})
輸出:git
a { name: 'wdd' } MyEmitter { domain: null, _events: { event: [ [Function], [Function] ] }, _eventsCount: 1, _maxListeners: undefined } true a { name: 'wdd' } {} false
同步
按照事件註冊的順序執行回調// 03.js const EventEmitter = require('events') class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter() myEmitter.on('event', () => { console.log('01 an event occurred!') }) myEmitter.on('event', () => { console.log('02 an event occurred!') }) console.log(1) myEmitter.emit('event') console.log(2)
輸出:github
1 01 an event occurred! 02 an event occurred! 2
深刻思考,爲何事件回調要同步?異步了會有什麼問題?
bootstrap
同步去調用事件監聽者,可以確保按照註冊順序去調用事件監聽者,而且避免競態條件和邏輯錯誤。dom
// 04.js const EventEmitter = require('events') class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter() let m = 0 myEmitter.once('event', () => { console.log(++m) }) myEmitter.emit('event') myEmitter.emit('event')
error
是一個特別的事件名,當這個事件被觸發時,若是沒有對應的事件監聽者,則會致使程序崩潰。異步
events.js:183 throw er; // Unhandled 'error' event ^ Error: test at Object.<anonymous> (/Users/xxx/github/node-note/events/05.js:12:25) at Module._compile (module.js:635:30) at Object.Module._extensions..js (module.js:646:10) at Module.load (module.js:554:32) at tryModuleLoad (module.js:497:12) at Function.Module._load (module.js:489:3) at Function.Module.runMain (module.js:676:10) at startup (bootstrap_node.js:187:16) at bootstrap_node.js:608:3
因此,最好老是給EventEmitter實例添加一個error的監聽器
函數
const EventEmitter = require('events') class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter() myEmitter.on('error', (err) => { console.log(err) }) console.log(1) myEmitter.emit('error', new Error('test')) console.log(2)
newListener與removeListener是EventEmitter實例的自帶的事件,你最好不要使用一樣的名字做爲自定義的事件名。ui
// 06.js const EventEmitter = require('events') class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter() myEmitter.on('newListener', (event, listener) => { console.log('----') console.log(event) console.log(listener) }) myEmitter.on('myEmitter', (err) => { console.log(err) })
輸出:this
從輸出能夠看出,即便沒有去觸發myEmitter事件,on()方法也會觸發newListener事件。code
---- myEmitter [Function]
EventEmitter和EventEmitter實例的最大監聽數量爲10並非一個硬性規定,只是一個推薦值,該值能夠經過setMaxListeners()接口去改變。
如無必要,最好的不要去改變默認的監聽數量限制。事件監聽數量是node檢測內存泄露的一個標準一個維度。
EventEmitter實例的最大監聽數量不是一個實例的全部監聽數量。
例如同一個實例A類型事件5個監聽者,B類型事件6個監聽者,這個並不會有告警。若是A類型有11個監聽者,就會有告警提示。
若是在事件中發現相似的告警提示Possible EventEmitter memory leak detected
,要知道從事件最大監聽數的角度去排查問題。
// 07.js const EventEmitter = require('events') class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter() const maxListeners = 11 for (let i = 0; i < maxListeners; i++) { myEmitter.on('event', (err) => { console.log(err, 1) }) } myEmitter.on('event1', (err) => { console.log(err, 11) }) console.log(myEmitter.listenerCount('event')) console.log(EventEmitter.defaultMaxListeners) console.log(myEmitter.getMaxListeners()) console.log(myEmitter.eventNames())
輸出:
11 10 10 [ 'event', 'event1' ] (node:23957) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 event listeners added. Use emitter.setMaxListeners() to increase limit