Node.js EventEmitter 筆記

跳一跳發表於2018-03-31

說起Node中幾個最重要的模組,那麼events模組一定在其中,在Node中很多很多的其他模組都是基於或者依賴於events模組。

那麼我們來了解一下什麼是events模組和events模組的使用,和一些注意點

我們參看的Node v6.10.3文件, 對於EventEmitter的方法我們不解釋,相對比較簡單,官方也給出了較多的例子,完全可以參看官方的文件,這裡就說明一些注意點

EventEmitter例項化

首先很多的教程裡面會寫以下的程式碼來例項化一個EventEmitter

  var events = require('events');
  var emitter = new events.EventEmitter();
複製程式碼

但是官方給出的例子卻是

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
複製程式碼

REPL中輸出const EventEmitter = require('events');中的EventEmitter

EventEmitter
{ [Function: EventEmitter]
  EventEmitter: [Circular], // 迴圈引用
  usingDomains: true,
  defaultMaxListeners: [Getter/Setter],
  init: [Function],
  listenerCount: [Function] }
複製程式碼

同時在翻看原始碼之後看到

module.exports = EventEmitter;

// Backwards-compat with node 0.10.x
EventEmitter.EventEmitter = EventEmitter;
複製程式碼

所以,兩種方式都是可以的,但是感覺按照官方的方式會更好。

error事件

當 EventEmitter 例項中發生錯誤時,會觸發一個 'error' 事件。 這在 Node.js 中是特殊情況。

如果 EventEmitter 沒有為 'error' 事件註冊至少一個監聽器,則當 'error' 事件觸發時,會丟擲錯誤、列印堆疊跟蹤、且退出 Node.js 程式。

const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// 丟擲錯誤,並使 Node.js 奔潰
複製程式碼

所以應該始終為 'error' 事件註冊監聽器。

myEmitter.on('error', (err) => {
  console.error('有錯誤');
});
複製程式碼

另外提一句為了防止 Node.js 程式崩潰,可以在 process 物件的 uncaughtException 事件上註冊監聽器。

const myEmitter = new MyEmitter();

process.on('uncaughtException', (err) => {
  console.error('有錯誤');
});

myEmitter.emit('error', new Error('whoops!'));
複製程式碼

this作用域

在ES6加入後,有了箭頭函式,有時候會導致監聽器的this作用域的不同,這裡需要稍微注意一下

const myEmitter = new MyEmitter();
myEmitter.on('event', function(a, b) {
  console.log(a, b, this);
  // 列印:
  //   a b MyEmitter {
  //     domain: null,
  //     _events: { event: [Function] },
  //     _eventsCount: 1,
  //     _maxListeners: undefined }
});
myEmitter.emit('event', 'a', 'b');
複製程式碼

箭頭函式版本

const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
  console.log(a, b, this);
  // 列印: a b {}
});
myEmitter.emit('event', 'a', 'b');
複製程式碼

相信瞭解過箭頭函式的原理的都應該可以理解。

on()addListener() 的區別

沒有區別

EventEmitter.prototype.on = EventEmitter.prototype.addListener;
複製程式碼

相關文章