Node.js v25.0.0 文件
- Node.js v25.0.0
-
目錄
- 事件
- 向監聽器傳遞引數和
this - 非同步 vs. 同步
- 僅處理一次事件
- 錯誤事件
- 捕獲 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.defaultMaxListenersevents.errorMonitorevents.getEventListeners(emitterOrTarget, eventName)events.getMaxListeners(emitterOrTarget)events.once(emitter, name[, options])events.captureRejectionsevents.captureRejectionSymbolevents.listenerCount(emitter, eventName)events.on(emitter, eventName[, options])events.setMaxListeners(n[, ...eventTargets])events.addAbortListener(signal, listener)- 類:
events.EventEmitterAsyncResource extends EventEmitter EventTarget和EventAPI- Node.js
EventTarget與 DOMEventTarget的對比 NodeEventTarget與EventEmitter的對比- 事件監聽器
EventTarget錯誤處理- 類:
Eventevent.bubblesevent.cancelBubbleevent.cancelableevent.composedevent.composedPath()event.currentTargetevent.defaultPreventedevent.eventPhaseevent.initEvent(type[, bubbles[, cancelable]])event.isTrustedevent.preventDefault()event.returnValueevent.srcElementevent.stopImmediatePropagation()event.stopPropagation()event.targetevent.timeStampevent.type
- 類:
EventTarget - 類:
CustomEvent - 類:
NodeEventTargetnodeEventTarget.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
- 子程序
- 叢集
- 命令列選項
- 控制檯
- 加密
- 偵錯程式
- 已棄用的 API
- 診斷通道
- DNS
- 域
- 環境變數
- 錯誤
- 事件
- 檔案系統
- 全域性物件
- HTTP
- HTTP/2
- HTTPS
- 檢查器
- 國際化
- 模組:CommonJS 模組
- 模組:ECMAScript 模組
- 模組:
node:moduleAPI - 模組:包
- 模組:TypeScript
- 網路
- 作業系統
- 路徑
- 效能鉤子
- 許可權
- 程序
- Punycode
- 查詢字串
- 逐行讀取
- REPL
- 報告
- 單一可執行檔案應用
- SQLite
- 流
- 字串解碼器
- 測試執行器
- 定時器
- TLS/SSL
- 跟蹤事件
- TTY
- UDP/資料報
- URL
- 實用工具
- V8
- 虛擬機器
- 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');
非同步 vs. 同步#
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: 2const 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');
// Ignoredconst 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.jsconst 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 errorconst 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.jsconst { 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' 事件沒有捕獲處理程式,以避免無限的錯誤迴圈:建議是不要使用 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
// Aconst 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<string> | <symbol> 事件名稱listener<Function> 事件處理函式
'removeListener' 事件在 listener 被移除之後發出。
emitter.addListener(eventName, listener)#
eventName<string> | <symbol>listener<Function>
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 listenerconst 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()#
- 返回:<string[]> | <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<string> | <symbol>- 返回:<Function[]>
返回名為 eventName 的事件的監聽器陣列的副本。
server.on('connection', (stream) => {
console.log('someone connected!');
});
console.log(util.inspect(server.listeners('connection')));
// Prints: [ [Function] ]
emitter.off(eventName, listener)#
eventName<string> | <symbol>listener<Function>- 返回:<EventEmitter>
emitter.on(eventName, listener)#
eventName<string> | <symbol> 事件的名稱。listener<Function> 回撥函式- 返回:<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
// aconst 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<string> | <symbol> 事件的名稱。listener<Function> 回撥函式- 返回:<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
// aconst 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<string> | <symbol> 事件的名稱。listener<Function> 回撥函式- 返回:<EventEmitter>
將 listener 函式新增到名為 eventName 的事件的監聽器陣列的開頭。不檢查 listener 是否已被新增。多次傳遞相同的 eventName 和 listener 組合將導致 listener 被多次新增和呼叫。
server.prependListener('connection', (stream) => {
console.log('someone connected!');
});
返回對 EventEmitter 的引用,以便可以鏈式呼叫。
emitter.prependOnceListener(eventName, listener)#
eventName<string> | <symbol> 事件的名稱。listener<Function> 回撥函式- 返回:<EventEmitter>
為名為 eventName 的事件新增一個一次性的 listener 函式到監聽器陣列的開頭。下次觸發 eventName 事件時,此監聽器將被移除,然後被呼叫。
server.prependOnceListener('connection', (stream) => {
console.log('Ah, we have our first user!');
});
返回對 EventEmitter 的引用,以便可以鏈式呼叫。
emitter.removeAllListeners([eventName])#
eventName<string> | <symbol>- 返回:<EventEmitter>
移除所有監聽器,或指定 eventName 的監聽器。
移除在程式碼其他地方新增的監聽器是一種不好的做法,特別是當 EventEmitter 例項是由其他元件或模組(例如套接字或檔案流)建立時。
返回對 EventEmitter 的引用,以便可以鏈式呼叫。
emitter.removeListener(eventName, listener)#
eventName<string> | <symbol>listener<Function>- 返回:<EventEmitter>
從名為 eventName 的事件的監聽器陣列中移除指定的 listener。
const callback = (stream) => {
console.log('someone connected!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback);
removeListener() 最多會從監聽器陣列中移除一個監聽器例項。如果某個監聽器已多次新增到指定 eventName 的監聽器陣列中,則必須多次呼叫 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:
// Aconst 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<integer>- 返回:<EventEmitter>
預設情況下,如果為特定事件添加了超過 10 個監聽器,EventEmitter 會列印一個警告。這是一個有用的預設設定,有助於發現記憶體洩漏。emitter.setMaxListeners() 方法允許為這個特定的 EventEmitter 例項修改此限制。該值可以設定為 Infinity(或 0)以表示無限數量的監聽器。
返回對 EventEmitter 的引用,以便可以鏈式呼叫。
emitter.rawListeners(eventName)#
eventName<string> | <symbol>- 返回:<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])#
如果在發出事件時發生 promise 拒絕,並且在發射器上啟用了 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() 方法臨時避免此警告。
defaultMaxListeners 對 AbortSignal 例項沒有影響。雖然仍然可以使用 emitter.setMaxListeners(n) 為單個 AbortSignal 例項設定警告限制,但預設情況下 AbortSignal 例項不會發出警告。
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<string> | <symbol>- 返回:<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> | <symbol>options<Object>signal<AbortSignal> 可用於取消等待事件。
- 返回:<Promise>
建立一個 Promise,當 EventEmitter 發出給定事件時,該 Promise 會被兌現;或者如果在等待期間 EventEmitter 發出 'error',則該 Promise 會被拒絕。該 Promise 將以一個包含所有傳遞給給定事件的引數的陣列來解決。
此方法特意設計為通用的,並且適用於 Web 平臺的 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();
對 'error' 事件的特殊處理僅在 events.once() 用於等待另一個事件時使用。如果 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 boomconst { 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(); // 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(); // 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,然後就可以使用 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#
- 型別:<boolean>
更改所有新 EventEmitter 物件上的預設 captureRejections 選項。
events.captureRejectionSymbol#
- 型別:<symbol>
Symbol.for('nodejs.rejection')
參見如何編寫自定義拒絕處理程式。
events.listenerCount(emitter, eventName)#
emitter.listenerCount()。emitter<EventEmitter> 要查詢的發射器eventName<string> | <symbol> 事件名稱
一個類方法,返回在給定 emitter 上為給定 eventName 註冊的監聽器數量。
import { EventEmitter, listenerCount } from 'node:events';
const myEmitter = new EventEmitter();
myEmitter.on('event', () => {});
myEmitter.on('event', () => {});
console.log(listenerCount(myEmitter, 'event'));
// Prints: 2const { 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> 可用於取消等待事件。close<string[]> 將結束迭代的事件名稱。highWaterMark<integer> 預設值:Number.MAX_SAFE_INTEGER高水位線。每當緩衝事件的大小高於它時,發射器就會暫停。僅在實現了pause()和resume()方法的發射器上支援。lowWaterMark<integer> 預設值:1低水位線。每當緩衝事件的大小低於它時,發射器就會恢復。僅在實現了pause()和resume()方法的發射器上支援。
- 返回:<AsyncIterator> 迭代由
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 hereconst { 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 事件的 AsyncIterator。如果 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<number> 一個非負數。每個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 事件是不安全的,可能會導致資源洩漏,因為擁有該訊號的第三方可以呼叫 e.stopImmediatePropagation()。不幸的是,Node.js 無法改變這一點,因為這會違反 Web 標準。此外,原始 API 很容易讓人忘記移除監聽器。
此 API 透過以一種方式監聽事件,使得 stopImmediatePropagation 不會阻止監聽器執行,從而解決了這兩個問題,允許在 Node.js API 中安全地使用 AbortSignal。
返回一個 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 自身相同的方法和選項。
new events.EventEmitterAsyncResource([options])#
options<Object>captureRejections<boolean> 它啟用自動捕獲 promise 拒絕。預設值:false。name<string> 非同步事件的型別。預設值:new.target.name。triggerAsyncId<number> 建立此非同步事件的執行上下文的 ID。預設值:executionAsyncId()。requireManualDestroy<boolean> 如果設定為true,則在物件被垃圾回收時停用emitDestroy。通常不需要設定此項(即使手動呼叫emitDestroy),除非檢索了資源的asyncId並使用它呼叫了敏感 API 的emitDestroy。當設定為false時,僅當至少有一個活動的destroy鉤子時,垃圾回收時的emitDestroy呼叫才會發生。預設值:false。
eventemitterasyncresource.asyncResource#
- 型別:<AsyncResource> 底層的 <AsyncResource>。
返回的 AsyncResource 物件有一個額外的 eventEmitter 屬性,提供了對此 EventEmitterAsyncResource 的引用。
eventemitterasyncresource.emitDestroy()#
呼叫所有 destroy 鉤子。這應該只被呼叫一次。如果呼叫超過一次,將丟擲錯誤。這必須手動呼叫。如果資源被垃圾回收器收集,destroy 鉤子將永遠不會被呼叫。
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不模擬完整的EventEmitterAPI。具體來說,prependListener()、prependOnceListener()、rawListeners()和errorMonitorAPI 不被模擬。'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 不像 EventEmitter 那樣為 'error' 型別的事件實現任何特殊的預設處理。
目前,錯誤會先轉發到 process.on('error') 事件,然後才到達 process.on('uncaughtException')。此行為已被棄用,並將在未來版本中更改,以使 EventTarget 與其他 Node.js API 保持一致。任何依賴 process.on('error') 事件的程式碼都應與新行為保持一致。
類:Event#
Event 物件是 Event Web API 的一個改編版。例項由 Node.js 內部建立。
event.cancelBubble#
event.stopPropagation()。- 型別:<boolean>
如果設定為 true,則是 event.stopPropagation() 的別名。這在 Node.js 中未使用,提供它純粹是為了完整性。
event.composedPath()#
返回一個包含當前 EventTarget 作為唯一條目的陣列,如果事件未被分派,則返回空陣列。這在 Node.js 中未使用,提供它純粹是為了完整性。
event.initEvent(type[, bubbles[, cancelable]])#
與事件建構函式功能重複,且無法設定 composed。這在 Node.js 中未使用,提供它純粹是為了完整性。
event.preventDefault()#
如果 cancelable 為 true,則將 defaultPrevented 屬性設定為 true。
event.returnValue#
event.defaultPrevented。- 型別:<boolean> 如果事件未被取消,則為 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。
類:EventTarget#
eventTarget.addEventListener(type, listener[, options])#
type<string>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>- 返回:<boolean> 如果事件的
cancelable屬性值為 false 或其preventDefault()方法未被呼叫,則為true,否則為false。
將 event 分派給 event.type 的處理程式列表。
註冊的事件監聽器會按照它們註冊的順序同步呼叫。
eventTarget.removeEventListener(type, listener[, options])#
type<string>listener<Function> | <EventListener>options<Object>capture<boolean>
從事件 type 的處理程式列表中移除 listener。
類:NodeEventTarget#
- 擴充套件:<EventTarget>
NodeEventTarget 是 EventTarget 的一個 Node.js 特定擴充套件,它模擬了 EventEmitter API 的一個子集。
nodeEventTarget.addListener(type, listener)#
-
type<string> -
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.off(type, listener[, options])#
-
type<string> -
listener<Function> | <EventListener> -
options<Object>capture<boolean>
-
返回:<EventTarget> this
eventTarget.removeEventListener() 的 Node.js 特定別名。
nodeEventTarget.on(type, listener)#
-
type<string> -
listener<Function> | <EventListener> -
返回:<EventTarget> this
eventTarget.addEventListener() 的 Node.js 特定別名。
nodeEventTarget.once(type, listener)#
-
type<string> -
listener<Function> | <EventListener> -
返回:<EventTarget> this
EventTarget 類的 Node.js 特定擴充套件,為給定的事件 type 新增一個 once 監聽器。這等同於呼叫 on 並將 once 選項設定為 true。
nodeEventTarget.removeAllListeners([type])#
-
type<string> -
返回:<EventTarget> this
EventTarget 類的 Node.js 特定擴充套件。如果指定了 type,則移除所有為 type 註冊的監聽器,否則移除所有已註冊的監聽器。
nodeEventTarget.removeListener(type, listener[, options])#
-
type<string> -
listener<Function> | <EventListener> -
options<Object>capture<boolean>
-
返回:<EventTarget> this
EventTarget 類的 Node.js 特定擴充套件,為給定的 type 移除 listener。removeListener() 和 removeEventListener() 之間的唯一區別是 removeListener() 會返回對 EventTarget 的引用。