Node.js v21.7.2 文件
- Node.js v21.7.2
-
► 目錄
- 事件
- 傳遞參數和
this
給監聽器 - 非同步與同步
- 只處理一次事件
- 錯誤事件
- 擷取 Promise 的拒絕
- 類別:
EventEmitter
- 事件:
'newListener'
- 事件:
'removeListener'
emitter.addListener(eventName, listener)
emitter.emit(eventName[, ...args])
emitter.eventNames()
emitter.getMaxListeners()
emitter.listenerCount(eventName[, listener])
emitter.listeners(eventName)
emitter.off(eventName, listener)
emitter.on(eventName, listener)
emitter.once(eventName, listener)
emitter.prependListener(eventName, listener)
emitter.prependOnceListener(eventName, listener)
emitter.removeAllListeners([eventName])
emitter.removeListener(eventName, listener)
emitter.setMaxListeners(n)
emitter.rawListeners(eventName)
emitter[Symbol.for('nodejs.rejection')](err, eventName[, ...args])
- 事件:
events.defaultMaxListeners
events.errorMonitor
events.getEventListeners(emitterOrTarget, eventName)
events.getMaxListeners(emitterOrTarget)
events.once(emitter, name[, options])
events.captureRejections
events.captureRejectionSymbol
events.listenerCount(emitter, eventName)
events.on(emitter, eventName[, options])
events.setMaxListeners(n[, ...eventTargets])
events.addAbortListener(signal, listener)
- 類別:
events.EventEmitterAsyncResource extends EventEmitter
EventTarget
和Event
API- Node.js
EventTarget
相對於 DOMEventTarget
NodeEventTarget
相對於EventEmitter
- 事件監聽器
EventTarget
錯誤處理- 類別:
Event
event.bubbles
event.cancelBubble
event.cancelable
event.composed
event.composedPath()
event.currentTarget
event.defaultPrevented
event.eventPhase
event.initEvent(type[, bubbles[, cancelable]])
event.isTrusted
event.preventDefault()
event.returnValue
event.srcElement
event.stopImmediatePropagation()
event.stopPropagation()
event.target
event.timeStamp
event.type
- 類別:
EventTarget
- 類別:
CustomEvent
- 類別:
NodeEventTarget
nodeEventTarget.addListener(type, listener)
nodeEventTarget.emit(type, arg)
nodeEventTarget.eventNames()
nodeEventTarget.listenerCount(type)
nodeEventTarget.setMaxListeners(n)
nodeEventTarget.getMaxListeners()
nodeEventTarget.off(type, listener[, options])
nodeEventTarget.on(type, listener)
nodeEventTarget.once(type, listener)
nodeEventTarget.removeAllListeners([type])
nodeEventTarget.removeListener(type, listener[, options])
- Node.js
- 傳遞參數和
- 事件
-
► 索引
- 斷言測試
- 非同步背景追蹤
- 非同步掛鉤
- 緩衝區
- C++ 外掛程式
- 使用 Node-API 的 C/C++ 外掛程式
- C++ 嵌入式 API
- 子程序
- 叢集
- 命令列選項
- 主控台
- Corepack
- 加密
- 偵錯程式
- 已棄用的 API
- 診斷頻道
- DNS
- 網域
- 錯誤
- 事件
- 檔案系統
- 全域變數
- HTTP
- HTTP/2
- HTTPS
- 檢查程式
- 國際化
- 模組:CommonJS 模組
- 模組:ECMAScript 模組
- 模組:
node:module
API - 模組:套件
- 網路
- 作業系統
- 路徑
- 效能掛鉤
- 權限
- 程序
- Punycode
- 查詢字串
- 讀取命令列
- REPL
- 報告
- 單一可執行應用程式
- 串流
- 字串解碼器
- 測試執行器
- 計時器
- TLS/SSL
- 追蹤事件
- TTY
- UDP/資料包
- URL
- 公用程式
- V8
- VM
- WASI
- Web Crypto API
- Web Streams API
- 工作執行緒
- Zlib
- ► 其他版本
- ► 選項
事件#
原始碼: lib/events.js
許多 Node.js 核心 API 建立在慣用的非同步事件驅動架構上,在這種架構中,某些類型的物件(稱為「發射器」)會發出命名事件,導致呼叫 Function
物件(「監聽器」)。
例如:net.Server
物件會在每次對等端連線時發出事件;fs.ReadStream
會在開啟檔案時發出事件;串流 會在有資料可讀取時發出事件。
所有會發出事件的物件都是 EventEmitter
類別的執行個體。這些物件會公開一個 eventEmitter.on()
函式,允許將一個或多個函式附加到物件所發出的命名事件。通常,事件名稱會使用駝峰式大小寫字串,但任何有效的 JavaScript 屬性金鑰都可以使用。
當 EventEmitter
物件發出事件時,附加到該特定事件的所有函式都會同步呼叫。呼叫的監聽器所傳回的任何值都會被忽略並捨棄。
下列範例顯示一個具有單一監聽器的簡單 EventEmitter
執行個體。eventEmitter.on()
方法用於註冊監聽器,而 eventEmitter.emit()
方法用於觸發事件。
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('an event occurred!');
});
myEmitter.emit('event');
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('an event occurred!');
});
myEmitter.emit('event');
傳遞引數和 this
給監聽器#
eventEmitter.emit()
方法允許將一組任意的引數傳遞給監聽器函式。請記住,當呼叫一般監聽器函式時,標準 this
關鍵字會故意設定為參照附加監聽器的 EventEmitter
執行個體。
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', function(a, b) {
console.log(a, b, this, this === myEmitter);
// Prints:
// a b MyEmitter {
// _events: [Object: null prototype] { event: [Function (anonymous)] },
// _eventsCount: 1,
// _maxListeners: undefined,
// [Symbol(shapeMode)]: false,
// [Symbol(kCapture)]: false
// } true
});
myEmitter.emit('event', 'a', 'b');
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', function(a, b) {
console.log(a, b, this, this === myEmitter);
// Prints:
// a b MyEmitter {
// _events: [Object: null prototype] { event: [Function (anonymous)] },
// _eventsCount: 1,
// _maxListeners: undefined,
// [Symbol(shapeMode)]: false,
// [Symbol(kCapture)]: false
// } true
});
myEmitter.emit('event', 'a', 'b');
可以將 ES6 箭頭函式用作監聽器,但是,這樣做時,this
關鍵字將不再參照 EventEmitter
執行個體。
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
console.log(a, b, this);
// Prints: a b undefined
});
myEmitter.emit('event', 'a', 'b');
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
console.log(a, b, this);
// Prints: a b {}
});
myEmitter.emit('event', 'a', 'b');
非同步與同步#
EventEmitter
會依據註冊順序同步呼叫所有監聽器。這可確保事件的正確順序,並有助於避免競爭條件和邏輯錯誤。在適當的情況下,監聽器函式可以使用 setImmediate()
或 process.nextTick()
方法切換到非同步操作模式
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
setImmediate(() => {
console.log('this happens asynchronously');
});
});
myEmitter.emit('event', 'a', 'b');
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
setImmediate(() => {
console.log('this happens asynchronously');
});
});
myEmitter.emit('event', 'a', 'b');
只處理事件一次#
當使用 eventEmitter.on()
方法註冊監聽器時,該監聽器會在每次發出指定事件時被呼叫。
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.on('event', () => {
console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Prints: 2
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.on('event', () => {
console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Prints: 2
使用 eventEmitter.once()
方法,可以註冊一個監聽器,該監聽器最多只會被呼叫一次以處理特定事件。一旦事件發出,監聽器就會被取消註冊,然後 才會被呼叫。
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.once('event', () => {
console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Ignored
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.once('event', () => {
console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Ignored
錯誤事件#
當 EventEmitter
執行個體內發生錯誤時,典型的動作是發出 'error'
事件。這些在 Node.js 中被視為特殊情況。
如果 EventEmitter
沒有 至少一個註冊的 'error'
事件監聽器,而 'error'
事件被發出,則會拋出錯誤、印出堆疊追蹤,且 Node.js 程序會結束。
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// Throws and crashes Node.js
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// Throws and crashes Node.js
為防止 Node.js 程序崩潰,可以使用 domain
模組。(但請注意,node:domain
模組已不建議使用。)
最佳實務是,應始終為 'error'
事件新增監聽器。
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('error', (err) => {
console.error('whoops! there was an error');
});
myEmitter.emit('error', new Error('whoops!'));
// Prints: whoops! there was an error
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('error', (err) => {
console.error('whoops! there was an error');
});
myEmitter.emit('error', new Error('whoops!'));
// Prints: whoops! there was an error
可以透過使用符號 events.errorMonitor
安裝監聽器,來監控 'error'
事件,而不會消耗發出的錯誤。
import { EventEmitter, errorMonitor } from 'node:events';
const myEmitter = new EventEmitter();
myEmitter.on(errorMonitor, (err) => {
MyMonitoringTool.log(err);
});
myEmitter.emit('error', new Error('whoops!'));
// Still throws and crashes Node.js
const { EventEmitter, errorMonitor } = require('node:events');
const myEmitter = new EventEmitter();
myEmitter.on(errorMonitor, (err) => {
MyMonitoringTool.log(err);
});
myEmitter.emit('error', new Error('whoops!'));
// Still throws and crashes Node.js
捕捉 Promise 的拒絕#
在事件處理常式中使用 async
函式是有問題的,因為在拋出例外情況時,可能會導致未處理的拒絕
import { EventEmitter } from 'node:events';
const ee = new EventEmitter();
ee.on('something', async (value) => {
throw new Error('kaboom');
});
const EventEmitter = require('node:events');
const ee = new EventEmitter();
ee.on('something', async (value) => {
throw new Error('kaboom');
});
EventEmitter
建構函式或全域設定中的 captureRejections
選項會變更此行為,在 Promise
上安裝一個 .then(undefined, handler)
處理常式。如果存在 Symbol.for('nodejs.rejection')
方法,此處理常式會非同步地將例外情況路由到該方法;如果不存在,則路由到 'error'
事件處理常式。
import { EventEmitter } from 'node:events';
const ee1 = new EventEmitter({ captureRejections: true });
ee1.on('something', async (value) => {
throw new Error('kaboom');
});
ee1.on('error', console.log);
const ee2 = new EventEmitter({ captureRejections: true });
ee2.on('something', async (value) => {
throw new Error('kaboom');
});
ee2[Symbol.for('nodejs.rejection')] = console.log;
const EventEmitter = require('node:events');
const ee1 = new EventEmitter({ captureRejections: true });
ee1.on('something', async (value) => {
throw new Error('kaboom');
});
ee1.on('error', console.log);
const ee2 = new EventEmitter({ captureRejections: true });
ee2.on('something', async (value) => {
throw new Error('kaboom');
});
ee2[Symbol.for('nodejs.rejection')] = console.log;
設定 events.captureRejections = true
會變更所有新 EventEmitter
執行個體的預設值。
import { EventEmitter } from 'node:events';
EventEmitter.captureRejections = true;
const ee1 = new EventEmitter();
ee1.on('something', async (value) => {
throw new Error('kaboom');
});
ee1.on('error', console.log);
const events = require('node:events');
events.captureRejections = true;
const ee1 = new events.EventEmitter();
ee1.on('something', async (value) => {
throw new Error('kaboom');
});
ee1.on('error', console.log);
由 captureRejections
行為產生的 'error'
事件沒有 catch 處理常式,以避免無限錯誤迴圈:建議不要將 async
函式用作 'error'
事件處理常式。
類別:EventEmitter
#
EventEmitter
類別由 node:events
模組定義和公開
import { EventEmitter } from 'node:events';
const EventEmitter = require('node:events');
所有 EventEmitter
都會在新增偵聽器時發出 'newListener'
事件,並在移除現有偵聽器時發出 'removeListener'
事件。
它支援下列選項
captureRejections
<boolean> 它啟用 自動擷取 Promise 拒絕。預設值:false
。
事件:'newListener'
#
eventName
<string> | <symbol> 偵聽的事件名稱listener
<Function> 事件處理常式函式
EventEmitter
實例會在偵聽器新增到其偵聽器內部陣列之前發出它自己的 'newListener'
事件。
為 'newListener'
事件註冊的偵聽器會傳遞事件名稱和對正在新增的偵聽器的參考。
事件在新增監聽器之前觸發,這會產生一個微妙但重要的副作用:任何在 'newListener'
回呼函數中註冊到同一個 name
的其他監聽器,會插入到正在新增的監聽器之前。
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
// Only do this once so we don't loop forever
myEmitter.once('newListener', (event, listener) => {
if (event === 'event') {
// Insert a new listener in front
myEmitter.on('event', () => {
console.log('B');
});
}
});
myEmitter.on('event', () => {
console.log('A');
});
myEmitter.emit('event');
// Prints:
// B
// A
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
// Only do this once so we don't loop forever
myEmitter.once('newListener', (event, listener) => {
if (event === 'event') {
// Insert a new listener in front
myEmitter.on('event', () => {
console.log('B');
});
}
});
myEmitter.on('event', () => {
console.log('A');
});
myEmitter.emit('event');
// Prints:
// B
// A
事件:'removeListener'
#
eventName
<字串> | <符號> 事件名稱listener
<Function> 事件處理常式函式
'removeListener'
事件會在移除 listener
之後 觸發。
emitter.addListener(eventName, listener)
#
emitter.on(eventName, listener)
的別名。
emitter.emit(eventName[, ...args])
#
同步呼叫已為命名為 eventName
的事件註冊的每個監聽器,按照它們的註冊順序,將提供的參數傳遞給每個監聽器。
如果事件有監聽器,則傳回 true
,否則傳回 false
。
import { EventEmitter } from 'node:events';
const myEmitter = new EventEmitter();
// First listener
myEmitter.on('event', function firstListener() {
console.log('Helloooo! first listener');
});
// Second listener
myEmitter.on('event', function secondListener(arg1, arg2) {
console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
});
// Third listener
myEmitter.on('event', function thirdListener(...args) {
const parameters = args.join(', ');
console.log(`event with parameters ${parameters} in third listener`);
});
console.log(myEmitter.listeners('event'));
myEmitter.emit('event', 1, 2, 3, 4, 5);
// Prints:
// [
// [Function: firstListener],
// [Function: secondListener],
// [Function: thirdListener]
// ]
// Helloooo! first listener
// event with parameters 1, 2 in second listener
// event with parameters 1, 2, 3, 4, 5 in third listener
const EventEmitter = require('node:events');
const myEmitter = new EventEmitter();
// First listener
myEmitter.on('event', function firstListener() {
console.log('Helloooo! first listener');
});
// Second listener
myEmitter.on('event', function secondListener(arg1, arg2) {
console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
});
// Third listener
myEmitter.on('event', function thirdListener(...args) {
const parameters = args.join(', ');
console.log(`event with parameters ${parameters} in third listener`);
});
console.log(myEmitter.listeners('event'));
myEmitter.emit('event', 1, 2, 3, 4, 5);
// Prints:
// [
// [Function: firstListener],
// [Function: secondListener],
// [Function: thirdListener]
// ]
// Helloooo! first listener
// event with parameters 1, 2 in second listener
// event with parameters 1, 2, 3, 4, 5 in third listener
emitter.eventNames()
#
- 傳回:<Array>
傳回一個陣列,列出已註冊監聽器的事件。陣列中的值是字串或 Symbol
。
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => {});
myEE.on('bar', () => {});
const sym = Symbol('symbol');
myEE.on(sym, () => {});
console.log(myEE.eventNames());
// Prints: [ 'foo', 'bar', Symbol(symbol) ]
const EventEmitter = require('node:events');
const myEE = new EventEmitter();
myEE.on('foo', () => {});
myEE.on('bar', () => {});
const sym = Symbol('symbol');
myEE.on(sym, () => {});
console.log(myEE.eventNames());
// Prints: [ 'foo', 'bar', Symbol(symbol) ]
emitter.getMaxListeners()
#
- 傳回:<integer>
傳回 EventEmitter
的目前最大監聽器值,該值會由 emitter.setMaxListeners(n)
設定,或預設為 events.defaultMaxListeners
。
emitter.listenerCount(eventName[, listener])
#
eventName
<string> | <symbol> 偵聽的事件名稱listener
<Function> 事件處理常式函式- 傳回:<integer>
傳回監聽名為 eventName
事件的監聽器數量。如果提供 listener
,它將傳回在事件監聽器清單中找到該監聽器的次數。
emitter.listeners(eventName)
#
eventName
<字串> | <符號>- 傳回:<Function[]>
傳回名為 eventName
事件的監聽器陣列副本。
server.on('connection', (stream) => {
console.log('someone connected!');
});
console.log(util.inspect(server.listeners('connection')));
// Prints: [ [Function] ]
emitter.off(eventName, listener)
#
eventName
<字串> | <符號>listener
<函數>- 傳回:<EventEmitter>
emitter.on(eventName, listener)
#
eventName
<字串> | <符號> 事件名稱。listener
<函式> 回呼函式- 傳回:<EventEmitter>
將 listener
函式新增到名為 eventName
事件的監聽器陣列尾端。不會檢查 listener
是否已新增。多次呼叫傳遞相同的 eventName
和 listener
組合,將會導致 listener
新增並呼叫多次。
server.on('connection', (stream) => {
console.log('someone connected!');
});
傳回對 EventEmitter
的參考,以便呼叫可以串連。
預設情況下,事件監聽器會按新增順序呼叫。emitter.prependListener()
方法可以用作將事件監聽器新增到監聽器陣列開頭的替代方案。
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a
const EventEmitter = require('node:events');
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a
emitter.once(eventName, listener)
#
eventName
<字串> | <符號> 事件名稱。listener
<函式> 回呼函式- 傳回:<EventEmitter>
為名為 eventName
的事件新增一個一次性 listener
函式。下次觸發 eventName
時,此監聽器會被移除,然後呼叫。
server.once('connection', (stream) => {
console.log('Ah, we have our first user!');
});
傳回對 EventEmitter
的參考,以便呼叫可以串連。
預設情況下,事件監聽器會按新增順序呼叫。emitter.prependOnceListener()
方法可以用作將事件監聽器新增到監聽器陣列開頭的替代方案。
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.once('foo', () => console.log('a'));
myEE.prependOnceListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a
const EventEmitter = require('node:events');
const myEE = new EventEmitter();
myEE.once('foo', () => console.log('a'));
myEE.prependOnceListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// a
emitter.prependListener(eventName, listener)
#
eventName
<字串> | <符號> 事件名稱。listener
<函式> 回呼函式- 傳回:<EventEmitter>
將 listener
函式新增到名為 eventName
事件的 listeners 陣列開頭。不會檢查 listener
是否已新增。多次呼叫傳遞相同的 eventName
和 listener
組合,將會導致 listener
被新增並呼叫多次。
server.prependListener('connection', (stream) => {
console.log('someone connected!');
});
傳回對 EventEmitter
的參考,以便呼叫可以串連。
emitter.prependOnceListener(eventName, listener)
#
eventName
<字串> | <符號> 事件名稱。listener
<函式> 回呼函式- 傳回:<EventEmitter>
將 eventName
事件的一次性 listener
函式新增到 listeners 陣列的開頭。下次觸發 eventName
時,此 listener 會被移除,然後呼叫。
server.prependOnceListener('connection', (stream) => {
console.log('Ah, we have our first user!');
});
傳回對 EventEmitter
的參考,以便呼叫可以串連。
emitter.removeAllListeners([eventName])
#
eventName
<字串> | <符號>- 傳回:<EventEmitter>
移除所有 listener,或移除指定 eventName
的 listener。
移除程式碼中其他位置新增的 listener 是不好的做法,特別是當 EventEmitter
執行個體是由其他元件或模組建立時(例如 socket 或檔案串流)。
傳回對 EventEmitter
的參考,以便呼叫可以串連。
emitter.removeListener(eventName, listener)
#
eventName
<字串> | <符號>listener
<函數>- 傳回:<EventEmitter>
從名為 eventName
事件的 listener 陣列中移除指定的 listener
。
const callback = (stream) => {
console.log('someone connected!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback);
removeListener()
最多會從 listener 陣列中移除 listener 的一個執行個體。如果任何單一 listener 已多次新增到指定 eventName
的 listener 陣列,則必須多次呼叫 removeListener()
才能移除每個執行個體。
一旦發出事件,所有在發出時附加到該事件的監聽器都會按順序被呼叫。這表示任何在發出之後和最後一個監聽器完成執行之前呼叫的 removeListener()
或 removeAllListeners()
都無法從正在進行的 emit()
中移除它們。後續事件的行為符合預期。
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
const callbackA = () => {
console.log('A');
myEmitter.removeListener('event', callbackB);
};
const callbackB = () => {
console.log('B');
};
myEmitter.on('event', callbackA);
myEmitter.on('event', callbackB);
// callbackA removes listener callbackB but it will still be called.
// Internal listener array at time of emit [callbackA, callbackB]
myEmitter.emit('event');
// Prints:
// A
// B
// callbackB is now removed.
// Internal listener array [callbackA]
myEmitter.emit('event');
// Prints:
// A
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
const callbackA = () => {
console.log('A');
myEmitter.removeListener('event', callbackB);
};
const callbackB = () => {
console.log('B');
};
myEmitter.on('event', callbackA);
myEmitter.on('event', callbackB);
// callbackA removes listener callbackB but it will still be called.
// Internal listener array at time of emit [callbackA, callbackB]
myEmitter.emit('event');
// Prints:
// A
// B
// callbackB is now removed.
// Internal listener array [callbackA]
myEmitter.emit('event');
// Prints:
// A
由於監聽器是使用內部陣列管理的,因此呼叫此方法會變更在移除監聽器之後註冊的任何監聽器的索引位置。這不會影響監聽器被呼叫的順序,但表示由 emitter.listeners()
方法傳回的任何監聽器陣列副本都需要重新建立。
當單一函式已多次新增為單一事件的處理常式(如下面的範例),removeListener()
會移除最近新增的執行個體。在範例中,once('ping')
監聽器會被移除
import { EventEmitter } from 'node:events';
const ee = new EventEmitter();
function pong() {
console.log('pong');
}
ee.on('ping', pong);
ee.once('ping', pong);
ee.removeListener('ping', pong);
ee.emit('ping');
ee.emit('ping');
const EventEmitter = require('node:events');
const ee = new EventEmitter();
function pong() {
console.log('pong');
}
ee.on('ping', pong);
ee.once('ping', pong);
ee.removeListener('ping', pong);
ee.emit('ping');
ee.emit('ping');
傳回對 EventEmitter
的參考,以便呼叫可以串連。
emitter.setMaxListeners(n)
#
n
<整數>- 傳回:<EventEmitter>
預設情況下,如果為特定事件新增超過 10
個監聽器,EventEmitter
會列印警告。這是一個有用的預設值,有助於找出記憶體外洩。emitter.setMaxListeners()
方法允許修改此特定 EventEmitter
執行個體的限制。可以將值設定為 Infinity
(或 0
)以表示無限數量的監聽器。
傳回對 EventEmitter
的參考,以便呼叫可以串連。
emitter.rawListeners(eventName)
#
eventName
<字串> | <符號>- 傳回:<Function[]>
傳回名為 eventName
的事件的監聽器陣列副本,包括任何包裝器(例如由 .once()
建立的包裝器)。
import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.once('log', () => console.log('log once'));
// Returns a new Array with a function `onceWrapper` which has a property
// `listener` which contains the original listener bound above
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];
// Logs "log once" to the console and does not unbind the `once` event
logFnWrapper.listener();
// Logs "log once" to the console and removes the listener
logFnWrapper();
emitter.on('log', () => console.log('log persistently'));
// Will return a new Array with a single function bound by `.on()` above
const newListeners = emitter.rawListeners('log');
// Logs "log persistently" twice
newListeners[0]();
emitter.emit('log');
const EventEmitter = require('node:events');
const emitter = new EventEmitter();
emitter.once('log', () => console.log('log once'));
// Returns a new Array with a function `onceWrapper` which has a property
// `listener` which contains the original listener bound above
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];
// Logs "log once" to the console and does not unbind the `once` event
logFnWrapper.listener();
// Logs "log once" to the console and removes the listener
logFnWrapper();
emitter.on('log', () => console.log('log persistently'));
// Will return a new Array with a single function bound by `.on()` above
const newListeners = emitter.rawListeners('log');
// Logs "log persistently" twice
newListeners[0]();
emitter.emit('log');
emitter[Symbol.for('nodejs.rejection')](err, eventName[, ...args])
#
如果在發出事件時發生承諾拒絕,且發出者已啟用 captureRejections
,則會呼叫 Symbol.for('nodejs.rejection')
方法。可以使用 events.captureRejectionSymbol
取代 Symbol.for('nodejs.rejection')
。
import { EventEmitter, captureRejectionSymbol } from 'node:events';
class MyClass extends EventEmitter {
constructor() {
super({ captureRejections: true });
}
[captureRejectionSymbol](err, event, ...args) {
console.log('rejection happened for', event, 'with', err, ...args);
this.destroy(err);
}
destroy(err) {
// Tear the resource down here.
}
}
const { EventEmitter, captureRejectionSymbol } = require('node:events');
class MyClass extends EventEmitter {
constructor() {
super({ captureRejections: true });
}
[captureRejectionSymbol](err, event, ...args) {
console.log('rejection happened for', event, 'with', err, ...args);
this.destroy(err);
}
destroy(err) {
// Tear the resource down here.
}
}
events.defaultMaxListeners
#
預設情況下,最多可以為任何單一事件註冊 10
個監聽器。可以使用 emitter.setMaxListeners(n)
方法為個別的 EventEmitter
實例變更此限制。若要變更所有 EventEmitter
實例的預設值,可以使用 events.defaultMaxListeners
屬性。如果這個值不是正數,則會擲出 RangeError
。
設定 events.defaultMaxListeners
時請小心,因為變更會影響所有 EventEmitter
實例,包括在變更之前建立的實例。不過,呼叫 emitter.setMaxListeners(n)
仍然優先於 events.defaultMaxListeners
。
這不是硬性限制。EventEmitter
實例將允許新增更多監聽器,但會在 stderr 中輸出追蹤警告,指出已偵測到「可能的 EventEmitter 記憶體外洩」。對於任何單一的 EventEmitter
,可以使用 emitter.getMaxListeners()
和 emitter.setMaxListeners()
方法暫時避免此警告
import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.setMaxListeners(emitter.getMaxListeners() + 1);
emitter.once('event', () => {
// do stuff
emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0));
});
const EventEmitter = require('node:events');
const emitter = new EventEmitter();
emitter.setMaxListeners(emitter.getMaxListeners() + 1);
emitter.once('event', () => {
// do stuff
emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0));
});
可以使用 --trace-warnings
命令列旗標顯示此類警告的堆疊追蹤。
可以使用 process.on('warning')
檢查發出的警告,並且會具有額外的 emitter
、type
和 count
屬性,分別指涉事件發射器實例、事件名稱和附加的監聽器數量。其 name
屬性設定為 'MaxListenersExceededWarning'
。
events.errorMonitor
#
此符號應僅用於安裝監聽器以監控 'error'
事件。使用此符號安裝的監聽器會在呼叫一般 'error'
監聽器之前呼叫。
使用此符號安裝監聽器不會在發出 'error'
事件後變更行為。因此,如果未安裝任何一般 'error'
監聽器,程序仍然會崩潰。
events.getEventListeners(emitterOrTarget, eventName)
#
emitterOrTarget
<EventEmitter> | <EventTarget>eventName
<字串> | <符號>- 傳回:<Function[]>
傳回名為 eventName
事件的監聽器陣列副本。
對於 EventEmitter
,這與在發射器上呼叫 .listeners
的行為完全相同。
對於 EventTarget
,這是取得事件目標的事件監聽器的唯一方法。這對於偵錯和診斷目的很有用。
import { getEventListeners, EventEmitter } from 'node:events';
{
const ee = new EventEmitter();
const listener = () => console.log('Events are fun');
ee.on('foo', listener);
console.log(getEventListeners(ee, 'foo')); // [ [Function: listener] ]
}
{
const et = new EventTarget();
const listener = () => console.log('Events are fun');
et.addEventListener('foo', listener);
console.log(getEventListeners(et, 'foo')); // [ [Function: listener] ]
}
const { getEventListeners, EventEmitter } = require('node:events');
{
const ee = new EventEmitter();
const listener = () => console.log('Events are fun');
ee.on('foo', listener);
console.log(getEventListeners(ee, 'foo')); // [ [Function: listener] ]
}
{
const et = new EventTarget();
const listener = () => console.log('Events are fun');
et.addEventListener('foo', listener);
console.log(getEventListeners(et, 'foo')); // [ [Function: listener] ]
}
events.getMaxListeners(emitterOrTarget)
#
emitterOrTarget
<EventEmitter> | <EventTarget>- 傳回:<number>
傳回目前設定的監聽器最大數量。
對於 EventEmitter
,這與在發射器上呼叫 .getMaxListeners
的行為完全相同。
對於 EventTarget
,這是取得事件目標的最大事件監聽器的唯一方法。如果單一 EventTarget 上的事件處理常式數量超過設定的最大值,EventTarget 會印出警告。
import { getMaxListeners, setMaxListeners, EventEmitter } from 'node:events';
{
const ee = new EventEmitter();
console.log(getMaxListeners(ee)); // 10
setMaxListeners(11, ee);
console.log(getMaxListeners(ee)); // 11
}
{
const et = new EventTarget();
console.log(getMaxListeners(et)); // 10
setMaxListeners(11, et);
console.log(getMaxListeners(et)); // 11
}
const { getMaxListeners, setMaxListeners, EventEmitter } = require('node:events');
{
const ee = new EventEmitter();
console.log(getMaxListeners(ee)); // 10
setMaxListeners(11, ee);
console.log(getMaxListeners(ee)); // 11
}
{
const et = new EventTarget();
console.log(getMaxListeners(et)); // 10
setMaxListeners(11, et);
console.log(getMaxListeners(et)); // 11
}
events.once(emitter, name[, options])
#
emitter
<EventEmitter>name
<string>options
<Object>signal
<AbortSignal> 可用於取消等待事件。
- 傳回:<Promise>
建立一個Promise
,當EventEmitter
發出指定的事件時,會達成此Promise
,或者在等待時,EventEmitter
發出'error'
時,會拒絕此Promise
。Promise
會解析為發出至指定事件的所有參數陣列。
此方法故意設計成通用的,並與網路平台EventTarget介面一起使用,此介面沒有特殊的'error'
事件語意,也不會偵聽'error'
事件。
import { once, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
process.nextTick(() => {
ee.emit('myevent', 42);
});
const [value] = await once(ee, 'myevent');
console.log(value);
const err = new Error('kaboom');
process.nextTick(() => {
ee.emit('error', err);
});
try {
await once(ee, 'myevent');
} catch (err) {
console.error('error happened', err);
}
const { once, EventEmitter } = require('node:events');
async function run() {
const ee = new EventEmitter();
process.nextTick(() => {
ee.emit('myevent', 42);
});
const [value] = await once(ee, 'myevent');
console.log(value);
const err = new Error('kaboom');
process.nextTick(() => {
ee.emit('error', err);
});
try {
await once(ee, 'myevent');
} catch (err) {
console.error('error happened', err);
}
}
run();
只有在使用events.once()
等待另一個事件時,才會特別處理'error'
事件。如果使用events.once()
等待'error'
事件本身,則會將其視為任何其他類型的事件,而不會特別處理
import { EventEmitter, once } from 'node:events';
const ee = new EventEmitter();
once(ee, 'error')
.then(([err]) => console.log('ok', err.message))
.catch((err) => console.error('error', err.message));
ee.emit('error', new Error('boom'));
// Prints: ok boom
const { EventEmitter, once } = require('node:events');
const ee = new EventEmitter();
once(ee, 'error')
.then(([err]) => console.log('ok', err.message))
.catch((err) => console.error('error', err.message));
ee.emit('error', new Error('boom'));
// Prints: ok boom
可以使用<AbortSignal>取消等待事件
import { EventEmitter, once } from 'node:events';
const ee = new EventEmitter();
const ac = new AbortController();
async function foo(emitter, event, signal) {
try {
await once(emitter, event, { signal });
console.log('event emitted!');
} catch (error) {
if (error.name === 'AbortError') {
console.error('Waiting for the event was canceled!');
} else {
console.error('There was an error', error.message);
}
}
}
foo(ee, 'foo', ac.signal);
ac.abort(); // Abort waiting for the event
ee.emit('foo'); // Prints: Waiting for the event was canceled!
const { EventEmitter, once } = require('node:events');
const ee = new EventEmitter();
const ac = new AbortController();
async function foo(emitter, event, signal) {
try {
await once(emitter, event, { signal });
console.log('event emitted!');
} catch (error) {
if (error.name === 'AbortError') {
console.error('Waiting for the event was canceled!');
} else {
console.error('There was an error', error.message);
}
}
}
foo(ee, 'foo', ac.signal);
ac.abort(); // Abort waiting for the event
ee.emit('foo'); // Prints: Waiting for the event was canceled!
等待在process.nextTick()
上發出的多個事件#
在使用events.once()
函式等待在同一批次process.nextTick()
作業中發出的多個事件,或每當多個事件同步發出時,有一個值得注意的邊界情況。特別是,因為process.nextTick()
佇列會在Promise
微任務佇列之前耗盡,而且因為EventEmitter
會同步發出所有事件,因此events.once()
可能會錯過一個事件。
import { EventEmitter, once } from 'node:events';
import process from 'node:process';
const myEE = new EventEmitter();
async function foo() {
await once(myEE, 'bar');
console.log('bar');
// This Promise will never resolve because the 'foo' event will
// have already been emitted before the Promise is created.
await once(myEE, 'foo');
console.log('foo');
}
process.nextTick(() => {
myEE.emit('bar');
myEE.emit('foo');
});
foo().then(() => console.log('done'));
const { EventEmitter, once } = require('node:events');
const myEE = new EventEmitter();
async function foo() {
await once(myEE, 'bar');
console.log('bar');
// This Promise will never resolve because the 'foo' event will
// have already been emitted before the Promise is created.
await once(myEE, 'foo');
console.log('foo');
}
process.nextTick(() => {
myEE.emit('bar');
myEE.emit('foo');
});
foo().then(() => console.log('done'));
若要捕捉兩個事件,請在等待其中任何一個事件之前建立每個Promise
,然後就可以使用Promise.all()
、Promise.race()
或Promise.allSettled()
import { EventEmitter, once } from 'node:events';
import process from 'node:process';
const myEE = new EventEmitter();
async function foo() {
await Promise.all([once(myEE, 'bar'), once(myEE, 'foo')]);
console.log('foo', 'bar');
}
process.nextTick(() => {
myEE.emit('bar');
myEE.emit('foo');
});
foo().then(() => console.log('done'));
const { EventEmitter, once } = require('node:events');
const myEE = new EventEmitter();
async function foo() {
await Promise.all([once(myEE, 'bar'), once(myEE, 'foo')]);
console.log('foo', 'bar');
}
process.nextTick(() => {
myEE.emit('bar');
myEE.emit('foo');
});
foo().then(() => console.log('done'));
events.captureRejections
#
值:<布林值>
變更所有新的 EventEmitter
物件上預設的 captureRejections
選項。
events.captureRejectionSymbol
#
值:Symbol.for('nodejs.rejection')
查看如何撰寫自訂 rejection 處理常式。
events.listenerCount(emitter, eventName)
#
emitter.listenerCount()
。emitter
<EventEmitter> 要查詢的發射器eventName
<字串> | <符號> 事件名稱
傳回在給定 emitter
上註冊的給定 eventName
的監聽器數量的類別方法。
import { EventEmitter, listenerCount } from 'node:events';
const myEmitter = new EventEmitter();
myEmitter.on('event', () => {});
myEmitter.on('event', () => {});
console.log(listenerCount(myEmitter, 'event'));
// Prints: 2
const { EventEmitter, listenerCount } = require('node:events');
const myEmitter = new EventEmitter();
myEmitter.on('event', () => {});
myEmitter.on('event', () => {});
console.log(listenerCount(myEmitter, 'event'));
// Prints: 2
events.on(emitter, eventName[, options])
#
emitter
<EventEmitter>eventName
<string> | <symbol> 偵聽的事件名稱options
<Object>signal
<AbortSignal> 可用於取消等待事件。
- 傳回:<非同步迭代器>,用於反覆處理
emitter
發出的eventName
事件
import { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo')) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
const { on, EventEmitter } = require('node:events');
(async () => {
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo')) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
})();
傳回反覆處理 eventName
事件的 非同步迭代器
。如果 EventEmitter
發出 'error'
,它會擲回錯誤。在離開迴圈時,它會移除所有監聽器。每個反覆處理傳回的 value
都是一個陣列,由發出的事件引數組成。
<AbortSignal> 可用於取消等待事件
import { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ac = new AbortController();
(async () => {
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo', { signal: ac.signal })) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
})();
process.nextTick(() => ac.abort());
const { on, EventEmitter } = require('node:events');
const ac = new AbortController();
(async () => {
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo', { signal: ac.signal })) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
})();
process.nextTick(() => ac.abort());
events.setMaxListeners(n[, ...eventTargets])
#
n
<數字> 非負數字。每個EventTarget
事件的最大監聽器數量。...eventsTargets
<EventTarget[]> | <EventEmitter[]> 零個或多個 <EventTarget> 或 <EventEmitter> 執行個體。如果未指定任何執行個體,n
會設定為所有新建立的 <EventTarget> 和 <EventEmitter> 物件的預設最大值。
import { setMaxListeners, EventEmitter } from 'node:events';
const target = new EventTarget();
const emitter = new EventEmitter();
setMaxListeners(5, target, emitter);
const {
setMaxListeners,
EventEmitter,
} = require('node:events');
const target = new EventTarget();
const emitter = new EventEmitter();
setMaxListeners(5, target, emitter);
events.addAbortListener(signal, listener)
#
signal
<AbortSignal>listener
<Function> | <EventListener>- 傳回:<Disposable> 一個會移除
abort
監聽器的 Disposable。
在提供的 signal
上監聽 abort
事件一次。
監聽 abort 訊號上的 abort
事件並不安全,而且可能會導致資源外洩,因為具有訊號的另一個第三方可以呼叫 e.stopImmediatePropagation()
。很不幸地,Node.js 無法變更這一點,因為這會違反網路標準。此外,原始 API 很容易讓人忘記移除監聽器。
這個 API 允許在 Node.js API 中安全地使用 AbortSignal
,方法是解決這兩個問題,透過監聽事件,讓 stopImmediatePropagation
無法阻止監聽器執行。
傳回一個 disposable,以便可以更容易地取消訂閱。
const { addAbortListener } = require('node:events');
function example(signal) {
let disposable;
try {
signal.addEventListener('abort', (e) => e.stopImmediatePropagation());
disposable = addAbortListener(signal, (e) => {
// Do something when signal is aborted.
});
} finally {
disposable?.[Symbol.dispose]();
}
}
import { addAbortListener } from 'node:events';
function example(signal) {
let disposable;
try {
signal.addEventListener('abort', (e) => e.stopImmediatePropagation());
disposable = addAbortListener(signal, (e) => {
// Do something when signal is aborted.
});
} finally {
disposable?.[Symbol.dispose]();
}
}
類別:events.EventEmitterAsyncResource extends EventEmitter
#
將 EventEmitter
與 <AsyncResource> 整合,以供需要手動非同步追蹤的 EventEmitter
。特別是,由 events.EventEmitterAsyncResource
執行個體發出的所有事件都將在其 非同步內容 中執行。
import { EventEmitterAsyncResource, EventEmitter } from 'node:events';
import { notStrictEqual, strictEqual } from 'node:assert';
import { executionAsyncId, triggerAsyncId } from 'node:async_hooks';
// Async tracking tooling will identify this as 'Q'.
const ee1 = new EventEmitterAsyncResource({ name: 'Q' });
// 'foo' listeners will run in the EventEmitters async context.
ee1.on('foo', () => {
strictEqual(executionAsyncId(), ee1.asyncId);
strictEqual(triggerAsyncId(), ee1.triggerAsyncId);
});
const ee2 = new EventEmitter();
// 'foo' listeners on ordinary EventEmitters that do not track async
// context, however, run in the same async context as the emit().
ee2.on('foo', () => {
notStrictEqual(executionAsyncId(), ee2.asyncId);
notStrictEqual(triggerAsyncId(), ee2.triggerAsyncId);
});
Promise.resolve().then(() => {
ee1.emit('foo');
ee2.emit('foo');
});
const { EventEmitterAsyncResource, EventEmitter } = require('node:events');
const { notStrictEqual, strictEqual } = require('node:assert');
const { executionAsyncId, triggerAsyncId } = require('node:async_hooks');
// Async tracking tooling will identify this as 'Q'.
const ee1 = new EventEmitterAsyncResource({ name: 'Q' });
// 'foo' listeners will run in the EventEmitters async context.
ee1.on('foo', () => {
strictEqual(executionAsyncId(), ee1.asyncId);
strictEqual(triggerAsyncId(), ee1.triggerAsyncId);
});
const ee2 = new EventEmitter();
// 'foo' listeners on ordinary EventEmitters that do not track async
// context, however, run in the same async context as the emit().
ee2.on('foo', () => {
notStrictEqual(executionAsyncId(), ee2.asyncId);
notStrictEqual(triggerAsyncId(), ee2.triggerAsyncId);
});
Promise.resolve().then(() => {
ee1.emit('foo');
ee2.emit('foo');
});
EventEmitterAsyncResource
類別具有與 EventEmitter
和 AsyncResource
本身相同的 method,並採用相同的選項。
new events.EventEmitterAsyncResource([options])
#
options
<Object>captureRejections
<boolean> 它啟用 自動擷取 Promise 拒絕。預設值:false
。name
<字串> 非同步事件的類型。預設:new.target.name
。triggerAsyncId
<數字> 建立此非同步事件的執行內容 ID。預設:executionAsyncId()
。requireManualDestroy
<布林> 如果設為true
,當物件被垃圾回收時,會停用emitDestroy
。通常不需要設定(即使emitDestroy
手動呼叫),除非資源的asyncId
已擷取,且敏感 API 的emitDestroy
已使用它呼叫。如果設為false
,只有在至少有一個 activedestroy
掛勾時,垃圾回收的emitDestroy
呼叫才會發生。預設:false
。
eventemitterasyncresource.asyncId
#
- 類型:<數字> 指派給資源的唯一
asyncId
。
eventemitterasyncresource.asyncResource
#
- 類型:底層的 <AsyncResource>。
傳回的 AsyncResource
物件具有額外的 eventEmitter
屬性,提供對此 EventEmitterAsyncResource
的參考。
eventemitterasyncresource.emitDestroy()
#
呼叫所有 destroy
掛勾。這只應呼叫一次。如果呼叫超過一次,將會擲回錯誤。這必須手動呼叫。如果資源留待 GC 收集,則 destroy
掛勾將永遠不會被呼叫。
eventemitterasyncresource.triggerAsyncId
#
- 類型:<number> 傳遞給
AsyncResource
建構函式的triggerAsyncId
。
EventTarget
和 Event
API#
EventTarget
和 Event
物件是 EventTarget
Web API 的 Node.js 特定實作,由一些 Node.js 核心 API 公開。
const target = new EventTarget();
target.addEventListener('foo', (event) => {
console.log('foo event happened!');
});
Node.js EventTarget
與 DOM EventTarget
#
Node.js EventTarget
和 EventTarget
Web API 之間有兩個主要差異
- DOM
EventTarget
執行個體可能會是階層式的,但在 Node.js 中沒有階層和事件傳播的概念。也就是說,傳送至EventTarget
的事件不會透過嵌套目標物件的階層傳播,而每個目標物件可能都有自己的一組事件處理常式。 - 在 Node.js
EventTarget
中,如果事件監聽器是非同步函式或傳回Promise
,且傳回的Promise
遭拒絕,則會自動擷取拒絕並以與同步擲回例外狀況的監聽器相同的方式處理(詳情請參閱EventTarget
錯誤處理)。
NodeEventTarget
與 EventEmitter
#
NodeEventTarget
物件實作了 EventEmitter
API 的修改子集,讓它能在特定情況下嚴密模擬EventEmitter
。NodeEventTarget
不是EventEmitter
的執行個體,且在多數情況下無法取代 EventEmitter
。
- 與
EventEmitter
不同,任何給定的listener
每個事件type
最多只能註冊一次。嘗試多次註冊listener
會被忽略。 NodeEventTarget
沒有模擬完整的EventEmitter
API。特別是prependListener()
、prependOnceListener()
、rawListeners()
和errorMonitor
API 沒有被模擬。'newListener'
和'removeListener'
事件也不會被發射。NodeEventTarget
沒有實作任何'error'
類型的事件的特殊預設行為。NodeEventTarget
支援EventListener
物件以及函式作為所有事件類型的處理常式。
事件聆聽器#
為事件 type
註冊的事件聆聽器可以是 JavaScript 函式或具有 handleEvent
屬性的物件,其值為函式。
在任何情況下,處理常式函式都會使用傳遞給 eventTarget.dispatchEvent()
函式的 event
引數來呼叫。
非同步函式可以用作事件聆聽器。如果非同步處理常式函式被拒絕,拒絕會被捕捉並處理,如 EventTarget
錯誤處理 中所述。
一個處理常式函式拋出的錯誤不會阻止其他處理常式被呼叫。
處理常式函式的傳回值會被忽略。
處理常式總是按照加入的順序被呼叫。
處理常式函式可以變異 event
物件。
function handler1(event) {
console.log(event.type); // Prints 'foo'
event.a = 1;
}
async function handler2(event) {
console.log(event.type); // Prints 'foo'
console.log(event.a); // Prints 1
}
const handler3 = {
handleEvent(event) {
console.log(event.type); // Prints 'foo'
},
};
const handler4 = {
async handleEvent(event) {
console.log(event.type); // Prints 'foo'
},
};
const target = new EventTarget();
target.addEventListener('foo', handler1);
target.addEventListener('foo', handler2);
target.addEventListener('foo', handler3);
target.addEventListener('foo', handler4, { once: true });
EventTarget
錯誤處理#
當註冊的事件監聽器擲回(或傳回一個會拒絕的 Promise)時,預設會將錯誤視為 `process.nextTick()` 上的未捕捉例外。這表示 `EventTarget` 中的未捕捉例外會預設終止 Node.js 程序。
在事件監聽器中擲回不會停止呼叫其他註冊的處理常式。
`EventTarget` 沒有實作任何針對 `'error'` 類型事件的特殊預設處理,例如 `EventEmitter`。
目前錯誤會先轉送至 `process.on('error')` 事件,才會到達 `process.on('uncaughtException')`。此行為已不建議使用,且會在未來的版本中變更,以使 `EventTarget` 與其他 Node.js API 保持一致。任何依賴 `process.on('error')` 事件的程式碼都應與新行為保持一致。
類別:Event
#
`Event` 物件是 Event
Web API 的改編版本。執行個體是由 Node.js 內部建立。
event.bubbles
#
- 類型:<boolean> 永遠傳回
false
。
這在 Node.js 中並未使用,純粹為了完整性而提供。
event.cancelBubble
#
event.stopPropagation()
。- 類型:<boolean>
如果設為 true
,則為 event.stopPropagation()
的別名。這在 Node.js 中未使用,純粹為了完整性而提供。
event.cancelable
#
- 類型:<布林值> 如果事件是用
cancelable
選項建立的,則為 True。
event.composed
#
- 類型:<boolean> 永遠傳回
false
。
這在 Node.js 中並未使用,純粹為了完整性而提供。
event.composedPath()
#
傳回一個陣列,包含目前的 EventTarget
作為唯一的項目,如果事件未被發送,則為空。這在 Node.js 中未使用,純粹為了完整性而提供。
event.currentTarget
#
- 類型:<EventTarget> 發送事件的
EventTarget
。
event.target
的別名。
event.defaultPrevented
#
- 類型:<boolean>
如果 cancelable
為 true
且已呼叫 event.preventDefault()
,則為 true
。
event.eventPhase
#
- 類型:<數字> 在事件未被發送時傳回
0
,在事件被發送時傳回2
。
這在 Node.js 中並未使用,純粹為了完整性而提供。
event.initEvent(type[, bubbles[, cancelable]])
#
與事件建構函式重複,且無法設定 composed
。這在 Node.js 中未使用,僅為完整性而提供。
event.isTrusted
#
- 類型:<boolean>
<中斷訊號> "中斷"
事件會在 isTrusted
設為 true
的情況下發出。在所有其他情況下,其值為 false
。
event.preventDefault()
#
如果 cancelable
為 true
,則將 defaultPrevented
屬性設為 true
。
event.returnValue
#
event.defaultPrevented
。- 類型:<布林> 如果事件尚未取消,則為 True。
event.returnValue
的值永遠與 event.defaultPrevented
相反。這在 Node.js 中未使用,僅為完整性而提供。
event.srcElement
#
event.target
。- 類型:<EventTarget> 發送事件的
EventTarget
。
event.target
的別名。
event.stopImmediatePropagation()
#
在目前事件完成後停止呼叫事件監聽器。
event.stopPropagation()
#
這在 Node.js 中並未使用,純粹為了完整性而提供。
event.target
#
- 類型:<EventTarget> 發送事件的
EventTarget
。
event.timeStamp
#
- 類型:<number>
建立 Event
物件時的毫秒時間戳記。
event.type
#
- 類型:<string>
事件類型識別碼。
類別:EventTarget
#
eventTarget.addEventListener(type, listener[, options])
#
type
<字串>listener
<Function> | <EventListener>options
<Object>once
<boolean> 若為true
,則在第一次呼叫時自動移除監聽器。預設值:false
。passive
<boolean> 若為true
,則表示監聽器不會呼叫Event
物件的preventDefault()
方法。預設值:false
。capture
<boolean> Node.js 未直接使用。為 API 完整性而新增。預設值:false
。signal
<AbortSignal> 當呼叫所提供 AbortSignal 物件的abort()
方法時,將移除監聽器。
為 type
事件新增新的處理常式。任何指定的 listener
僅會針對每個 type
和每個 capture
選項值新增一次。
如果 once
選項為 true
,則在下次派送 type
事件後,將移除 listener
。
capture
選項不會以任何功能性的方式被 Node.js 使用,只會根據 EventTarget
規格追蹤已註冊的事件監聽器。具體來說,capture
選項在註冊 listener
時用作金鑰的一部分。任何個別的 listener
都可以新增一次,其中 capture = false
,並新增一次,其中 capture = true
。
function handler(event) {}
const target = new EventTarget();
target.addEventListener('foo', handler, { capture: true }); // first
target.addEventListener('foo', handler, { capture: false }); // second
// Removes the second instance of handler
target.removeEventListener('foo', handler);
// Removes the first instance of handler
target.removeEventListener('foo', handler, { capture: true });
eventTarget.dispatchEvent(event)
#
將 event
派送至 event.type
的處理常式清單。
已註冊的事件監聽器會以註冊順序同步呼叫。
eventTarget.removeEventListener(type, listener[, options])
#
type
<字串>listener
<Function> | <EventListener>options
<Object>capture
<boolean>
從事件 type
的處理常式清單中移除 listener
。
類別:CustomEvent
#
- 延伸:<Event>
CustomEvent
物件是 CustomEvent
Web API 的改編。執行個體由 Node.js 內部建立。
event.detail
#
- 類型:<any> 傳回初始化時傳遞的自訂資料。
唯讀。
類別:NodeEventTarget
#
NodeEventTarget
是 EventTarget
的 Node.js 特定延伸,模擬 EventEmitter
API 的子集。
nodeEventTarget.addListener(type, listener)
#
-
type
<字串> -
listener
<Function> | <EventListener> -
傳回:<EventTarget> this
EventTarget
類別的 Node.js 特定延伸,模擬等效的 EventEmitter
API。addListener()
和 addEventListener()
之間唯一的差異在於 addListener()
會傳回對 EventTarget
的參考。
nodeEventTarget.emit(type, arg)
#
EventTarget
類別的 Node.js 特定延伸,將 arg
傳送給 type
的處理常式清單。
nodeEventTarget.eventNames()
#
- 傳回:<string[]>
EventTarget
類別的 Node.js 特定延伸,傳回已註冊事件聆聽器的事件 type
名稱陣列。
nodeEventTarget.listenerCount(type)
#
EventTarget
類別的 Node.js 特定延伸,傳回已註冊 type
的事件聆聽器數量。
nodeEventTarget.setMaxListeners(n)
#
n
<number>
Node.js 特有的擴充套件,用於將最大事件監聽器數量設定為 n
的 EventTarget
類別。
nodeEventTarget.getMaxListeners()
#
- 傳回:<number>
Node.js 特有的擴充套件,用於傳回最大事件監聽器數量,用於 EventTarget
類別。
nodeEventTarget.off(type, listener[, options])
#
-
type
<字串> -
listener
<Function> | <EventListener> -
options
<Object>capture
<boolean>
-
傳回:<EventTarget> this
eventTarget.removeEventListener()
的 Node.js 特有別名。
nodeEventTarget.on(type, listener)
#
-
type
<字串> -
listener
<Function> | <EventListener> -
傳回:<EventTarget> this
eventTarget.addEventListener()
的 Node.js 特有別名。
nodeEventTarget.once(type, listener)
#
-
type
<字串> -
listener
<Function> | <EventListener> -
傳回:<EventTarget> this
Node.js 特有的擴充套件,用於針對指定的事件 type
新增 once
監聽器。這等於呼叫 on
,並將 once
選項設定為 true
。
nodeEventTarget.removeAllListeners([type])
#
-
type
<字串> -
傳回:<EventTarget> this
Node.js 特有的擴充套件,用於 EventTarget
類別。如果指定 type
,則移除所有已註冊的 type
監聽器,否則移除所有已註冊的監聽器。
nodeEventTarget.removeListener(type, listener[, options])
#
-
type
<字串> -
listener
<Function> | <EventListener> -
options
<Object>capture
<boolean>
-
傳回:<EventTarget> this
EventTarget
類別的 Node.js 專屬擴充功能,用於移除給定 type
的 listener
。removeListener()
和 removeEventListener()
之間唯一的差異是 removeListener()
會傳回對 EventTarget
的參考。