事件
源代码: 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)
// 打印:
// 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)
// 打印:
// 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)
// 打印: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)
// 打印: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')
// 打印:1
myEmitter.emit('event')
// 打印: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')
// 打印:1
myEmitter.emit('event')
// 打印: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')
// 打印:1
myEmitter.emit('event')
// 被忽略
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')
// 打印:1
myEmitter.emit('event')
// 被忽略
错误事件
当 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!'))
// 抛出错误并使 Node.js 崩溃
const EventEmitter = require('node:events')
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.emit('error', new Error('whoops!'))
// 抛出错误并使 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!'))
// 打印: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!'))
// 打印: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!'))
// 仍然抛出错误并使 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!'))
// 仍然抛出错误并使 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
[历史]
版本 | 变更 |
---|---|
v13.4.0, v12.16.0 | 添加了 captureRejections 选项。 |
v0.1.26 | 在 v0.1.26 中添加 |
EventEmitter
类由 node:events
模块定义和导出:
import { EventEmitter } from 'node:events'
const EventEmitter = require('node:events')
所有 EventEmitter
在添加新的监听器时都会发出 'newListener'
事件,在移除现有的监听器时会发出 'removeListener'
事件。
它支持以下选项:
captureRejections
<布尔值> 它启用自动捕获 Promise 拒绝。默认值:false
。
事件: 'newListener'
添加到:v0.1.26
EventEmitter
实例会在监听器添加到其内部监听器数组 之前 发出其自己的 'newListener'
事件。
为 'newListener'
事件注册的监听器会传递事件名称和对正在添加的监听器的引用。
该事件在添加监听器之前触发这一事实有一个细微但重要的副作用:在 'newListener'
回调中注册到相同 name
的任何 附加 监听器都会在正在添加的监听器 之前 插入。
import { EventEmitter } from 'node:events'
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
// 只执行一次,以免无限循环
myEmitter.once('newListener', (event, listener) => {
if (event === 'event') {
// 在前面插入一个新的监听器
myEmitter.on('event', () => {
console.log('B')
})
}
})
myEmitter.on('event', () => {
console.log('A')
})
myEmitter.emit('event')
// 打印:
// B
// A
const EventEmitter = require('node:events')
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
// 只执行一次,以免无限循环
myEmitter.once('newListener', (event, listener) => {
if (event === 'event') {
// 在前面插入一个新的监听器
myEmitter.on('event', () => {
console.log('B')
})
}
})
myEmitter.on('event', () => {
console.log('A')
})
myEmitter.emit('event')
// 打印:
// B
// A
事件:'removeListener'
[历史]
版本 | 变更 |
---|---|
v6.1.0, v4.7.0 | 使用 .once() 附加的监听器,listener 参数现在返回原始监听器函数。 |
v0.9.3 | 添加于:v0.9.3 |
'removeListener'
事件在 listener
移除 之后 触发。
emitter.addListener(eventName, listener)
添加于:v0.1.26
emitter.on(eventName, listener)
的别名。
emitter.emit(eventName[, ...args])
新增于:v0.1.26
同步调用为名为 eventName
的事件注册的每个监听器,按照注册顺序进行调用,并将提供的参数传递给每个监听器。
如果事件存在监听器,则返回 true
,否则返回 false
。
import { EventEmitter } from 'node:events'
const myEmitter = new EventEmitter()
// 第一个监听器
myEmitter.on('event', function firstListener() {
console.log('Helloooo! first listener')
})
// 第二个监听器
myEmitter.on('event', function secondListener(arg1, arg2) {
console.log(`event with parameters ${arg1}, ${arg2} in second 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)
// 输出:
// [
// [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()
// 第一个监听器
myEmitter.on('event', function firstListener() {
console.log('Helloooo! first listener')
})
// 第二个监听器
myEmitter.on('event', function secondListener(arg1, arg2) {
console.log(`event with parameters ${arg1}, ${arg2} in second 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)
// 输出:
// [
// [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()
新增于:v6.0.0
- 返回值:
<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())
// 输出: [ '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())
// 输出: [ 'foo', 'bar', Symbol(symbol) ]
emitter.getMaxListeners()
新增于:v1.0.0
- 返回值:
<number>
返回 EventEmitter
的当前最大监听器值,该值由 emitter.setMaxListeners(n)
设置,或者默认为 events.defaultMaxListeners
。
emitter.listenerCount(eventName[, listener])
[历史]
版本 | 变更 |
---|---|
v19.8.0, v18.16.0 | 新增 listener 参数。 |
v3.2.0 | 首次引入: v3.2.0 |
返回监听名为 eventName
的事件的监听器数量。如果提供了 listener
,则返回该监听器在事件监听器列表中出现的次数。
emitter.listeners(eventName)
[历史]
版本 | 变更 |
---|---|
v7.0.0 | 对于使用 .once() 附加的监听器,现在返回原始监听器而不是包装函数。 |
v0.1.26 | 首次引入: v0.1.26 |
返回名为 eventName
的事件的监听器数组的副本。
server.on('connection', stream => {
console.log('someone connected!')
})
console.log(util.inspect(server.listeners('connection')))
// 打印: [ [Function] ]
emitter.off(eventName, listener)
新增于: v10.0.0
eventName
<string> | <symbol>listener
<Function>- 返回值: <EventEmitter>
emitter.on(eventName, listener)
新增于: v0.1.101
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')
// 打印:
// 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')
// 打印:
// b
// a
emitter.once(eventName, listener)
新增于:v0.3.0
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')
// 打印:
// 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')
// 打印:
// b
// a
emitter.prependListener(eventName, listener)
新增于:v6.0.0
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)
新增于: v6.0.0
eventName
<string> | <symbol> 事件名称。listener
<Function> 回调函数- 返回值: <EventEmitter>
将一个一次性的 listener
函数添加到名为 eventName
的事件的监听器数组的开头。下次触发 eventName
时,此监听器将被移除,然后调用。
server.prependOnceListener('connection', stream => {
console.log('Ah, we have our first user!')
})
返回 EventEmitter
的引用,以便可以链式调用。
emitter.removeAllListeners([eventName])
新增于: v0.1.26
eventName
<string> | <symbol>- 返回值: <EventEmitter>
移除所有监听器,或指定 eventName
的监听器。
移除在代码其他地方添加的监听器是不好的做法,尤其是在 EventEmitter
实例由其他组件或模块(例如套接字或文件流)创建时。
返回 EventEmitter
的引用,以便可以链式调用。
emitter.removeListener(eventName, listener)
新增于:v0.1.26
eventName
<字符串> | <符号>listener
<函数>- 返回值:<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 移除监听器 callbackB,但它仍将被调用。
// 发射时的内部监听器数组 [callbackA, callbackB]
myEmitter.emit('event')
// 打印:
// A
// B
// callbackB 现在已移除。
// 内部监听器数组 [callbackA]
myEmitter.emit('event')
// 打印:
// 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 移除监听器 callbackB,但它仍将被调用。
// 发射时的内部监听器数组 [callbackA, callbackB]
myEmitter.emit('event')
// 打印:
// A
// B
// callbackB 现在已移除。
// 内部监听器数组 [callbackA]
myEmitter.emit('event')
// 打印:
// 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)
新增于: v0.3.5
n
<整数>- 返回值: <EventEmitter>
默认情况下,如果为特定事件添加了超过 10
个监听器,EventEmitter
将打印警告。这是一个有用的默认设置,有助于查找内存泄漏。emitter.setMaxListeners()
方法允许为此特定 EventEmitter
实例修改此限制。该值可以设置为 Infinity
(或 0
)以指示无限数量的监听器。
返回 EventEmitter
的引用,以便可以链接调用。
emitter.rawListeners(eventName)
新增于: v9.4.0
eventName
<字符串> | <符号>- 返回值: <Function[]>
返回名为 eventName
的事件的监听器数组的副本,包括任何包装器(例如由 .once()
创建的包装器)。
import { EventEmitter } from 'node:events'
const emitter = new EventEmitter()
emitter.once('log', () => console.log('log once'))
// 返回一个新数组,其中包含一个函数 `onceWrapper`,该函数具有一个属性
// `listener`,其中包含上面绑定的原始监听器
const listeners = emitter.rawListeners('log')
const logFnWrapper = listeners[0]
// 将“log once”记录到控制台,并且不取消绑定 `once` 事件
logFnWrapper.listener()
// 将“log once”记录到控制台并删除监听器
logFnWrapper()
emitter.on('log', () => console.log('log persistently'))
// 将返回一个新数组,其中包含上面由 `.on()` 绑定的单个函数
const newListeners = emitter.rawListeners('log')
// 将“log persistently”记录两次
newListeners[0]()
emitter.emit('log')
const EventEmitter = require('node:events')
const emitter = new EventEmitter()
emitter.once('log', () => console.log('log once'))
// 返回一个新数组,其中包含一个函数 `onceWrapper`,该函数具有一个属性
// `listener`,其中包含上面绑定的原始监听器
const listeners = emitter.rawListeners('log')
const logFnWrapper = listeners[0]
// 将“log once”记录到控制台,并且不取消绑定 `once` 事件
logFnWrapper.listener()
// 将“log once”记录到控制台并删除监听器
logFnWrapper()
emitter.on('log', () => console.log('log persistently'))
// 将返回一个新数组,其中包含上面由 `.on()` 绑定的单个函数
const newListeners = emitter.rawListeners('log')
// 将“log persistently”记录两次
newListeners[0]()
emitter.emit('log')
emitter[Symbol.for('nodejs.rejection')](err, eventName[, ...args])
[历史]
版本 | 变更 |
---|---|
v17.4.0, v16.14.0 | 移除实验性标识。 |
v13.4.0, v12.16.0 | v13.4.0, v12.16.0 版本中添加 |
当事件发出时发生 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) {
// 在此处销毁资源。
}
}
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) {
// 在此处销毁资源。
}
}
events.defaultMaxListeners
新增于:v0.11.2
默认情况下,任何单个事件最多可以注册 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
新增于:v13.6.0, v12.17.0
此符号用于安装仅监听 'error'
事件的监听器。使用此符号安装的监听器会在常规 'error'
监听器调用之前调用。
使用此符号安装监听器不会改变发出 'error'
事件后的行为。因此,如果没有安装常规的 'error'
监听器,进程仍然会崩溃。
events.getEventListeners(emitterOrTarget, eventName)
新增于:v15.2.0, v14.17.0
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)
新增于:v19.9.0, v18.17.0
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])
[历史]
版本 | 变更 |
---|---|
v15.0.0 | 现在支持 signal 选项。 |
v11.13.0, v10.16.0 | 添加于:v11.13.0, v10.16.0 |
emitter
<EventEmitter>options
<Object>signal
<AbortSignal> 可用于取消等待事件。
返回值: <Promise>
创建一个 Promise
,当 EventEmitter
发出给定事件时,该 Promise
就会 fulfilled;如果 EventEmitter
在等待过程中发出 'error'
事件,则该 Promise
就会 rejected。该 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()
只有当 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() // 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')
// 此 Promise 将永远不会被解决,因为 'foo' 事件将在创建 Promise 之前就已经发出。
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')
// 此 Promise 将永远不会被解决,因为 'foo' 事件将在创建 Promise 之前就已经发出。
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
[历史]
版本 | 变更 |
---|---|
v17.4.0, v16.14.0 | 移除实验性标识。 |
v13.4.0, v12.16.0 | v13.4.0, v12.16.0 版本中添加 |
值: <布尔值>
更改所有新的 EventEmitter
对象上的默认 captureRejections
选项。
events.captureRejectionSymbol
[历史]
版本 | 变更 |
---|---|
v17.4.0, v16.14.0 | 移除实验性标识。 |
v13.4.0, v12.16.0 | v13.4.0, v12.16.0 版本中添加 |
值: Symbol.for('nodejs.rejection')
查看如何编写自定义的 拒绝处理程序。
events.listenerCount(emitter, eventName)
添加于: v0.9.12
自 v3.2.0 起弃用
[稳定性: 0 - 已弃用]
稳定性: 0 稳定性: 0 - 已弃用: 请使用 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'))
// 输出: 2
const { EventEmitter, listenerCount } = require('node:events')
const myEmitter = new EventEmitter()
myEmitter.on('event', () => {})
myEmitter.on('event', () => {})
console.log(listenerCount(myEmitter, 'event'))
// 输出: 2
events.on(emitter, eventName[, options])
[历史]
版本 | 变更 |
---|---|
v22.0.0, v20.13.0 | 支持 highWaterMark 和 lowWaterMark 选项,为保持一致性。旧选项仍然支持。 |
v20.0.0 | 现在支持 close 、highWatermark 和 lowWatermark 选项。 |
v13.6.0, v12.16.0 | 新增于:v13.6.0, v12.16.0 |
emitter
<EventEmitter>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()
// 稍后发出
process.nextTick(() => {
ee.emit('foo', 'bar')
ee.emit('foo', 42)
})
for await (const event of on(ee, 'foo')) {
// 此内部块的执行是同步的,它一次处理一个事件(即使使用 await)。如果需要并发执行,请勿使用。
console.log(event) // 打印 ['bar'] [42]
}
// 此处不可达
const { on, EventEmitter } = require('node:events')
;(async () => {
const ee = new EventEmitter()
// 稍后发出
process.nextTick(() => {
ee.emit('foo', 'bar')
ee.emit('foo', 42)
})
for await (const event of on(ee, 'foo')) {
// 此内部块的执行是同步的,它一次处理一个事件(即使使用 await)。如果需要并发执行,请勿使用。
console.log(event) // 打印 ['bar'] [42]
}
// 此处不可达
})()
返回一个 AsyncIterator
,它迭代 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()
// 稍后发出
process.nextTick(() => {
ee.emit('foo', 'bar')
ee.emit('foo', 42)
})
for await (const event of on(ee, 'foo', { signal: ac.signal })) {
// 此内部块的执行是同步的,它一次处理一个事件(即使使用 await)。如果需要并发执行,请勿使用。
console.log(event) // 打印 ['bar'] [42]
}
// 此处不可达
})()
process.nextTick(() => ac.abort())
const { on, EventEmitter } = require('node:events')
const ac = new AbortController()
;(async () => {
const ee = new EventEmitter()
// 稍后发出
process.nextTick(() => {
ee.emit('foo', 'bar')
ee.emit('foo', 42)
})
for await (const event of on(ee, 'foo', { signal: ac.signal })) {
// 此内部块的执行是同步的,它一次处理一个事件(即使使用 await)。如果需要并发执行,请勿使用。
console.log(event) // 打印 ['bar'] [42]
}
// 此处不可达
})()
process.nextTick(() => ac.abort())
events.setMaxListeners(n[, ...eventTargets])
新增于:v15.4.0
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)
新增于: v20.5.0, v18.18.0
signal
<AbortSignal>listener
<Function> | <EventListener>- 返回值: <Disposable> 一个 Disposable 对象,用于移除
abort
监听器。
监听提供的 signal
上的 abort
事件一次。
监听中止信号上的 abort
事件是不安全的,并且可能导致资源泄漏,因为另一个拥有该信号的第三方可以调用 e.stopImmediatePropagation()
。不幸的是,Node.js 无法更改这一点,因为这会违反 Web 标准。此外,原始 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 => {
// 当信号中止时执行某些操作。
})
} 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 => {
// 当信号中止时执行某些操作。
})
} finally {
disposable?.[Symbol.dispose]()
}
}
类: events.EventEmitterAsyncResource extends EventEmitter
新增于: v17.4.0, v16.14.0
将 EventEmitter
与 <AsyncResource> 集成,用于需要手动异步跟踪的 EventEmitter
。具体来说,events.EventEmitterAsyncResource
实例发出的所有事件都将在其 异步上下文 中运行。
import { EventEmitterAsyncResource, EventEmitter } from 'node:events'
import { notStrictEqual, strictEqual } from 'node:assert'
import { executionAsyncId, triggerAsyncId } from 'node:async_hooks'
// 异步跟踪工具会将其识别为“Q”。
const ee1 = new EventEmitterAsyncResource({ name: 'Q' })
// 'foo' 监听器将在 EventEmitter 的异步上下文中运行。
ee1.on('foo', () => {
strictEqual(executionAsyncId(), ee1.asyncId)
strictEqual(triggerAsyncId(), ee1.triggerAsyncId)
})
const ee2 = new EventEmitter()
// 然而,在不跟踪异步上下文的普通 EventEmitter 上的 'foo' 监听器,将在与 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')
// 异步跟踪工具会将其识别为“Q”。
const ee1 = new EventEmitterAsyncResource({ name: 'Q' })
// 'foo' 监听器将在 EventEmitter 的异步上下文中运行。
ee1.on('foo', () => {
strictEqual(executionAsyncId(), ee1.asyncId)
strictEqual(triggerAsyncId(), ee1.triggerAsyncId)
})
const ee2 = new EventEmitter()
// 然而,在不跟踪异步上下文的普通 EventEmitter 上的 'foo' 监听器,将在与 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
<对象>captureRejections
<布尔值> 启用自动捕获 Promise 拒绝。默认值:false
。name
<字符串> 异步事件的类型。默认值:new.target.name
。triggerAsyncId
<数字> 创建此异步事件的执行上下文的 ID。默认值:executionAsyncId()
。requireManualDestroy
<布尔值> 如果设置为true
,则在对象被垃圾回收时禁用emitDestroy
。通常不需要设置此选项(即使手动调用emitDestroy
),除非检索资源的asyncId
并使用它调用敏感 API 的emitDestroy
。如果设置为false
,则只有当至少有一个活动的destroy
钩子时,垃圾回收才会调用emitDestroy
。默认值:false
。
eventemitterasyncresource.asyncId
- 类型: <数字> 分配给资源的唯一
asyncId
。
eventemitterasyncresource.asyncResource
- 类型: 底层的 <AsyncResource>。
返回的 AsyncResource
对象具有一个附加的 eventEmitter
属性,该属性提供对该 EventEmitterAsyncResource
的引用。
eventemitterasyncresource.emitDestroy()
调用所有 destroy
钩子。这只能调用一次。如果调用多次,则会抛出错误。这必须手动调用。如果资源被 GC 收集,则 destroy
钩子将永远不会被调用。
eventemitterasyncresource.triggerAsyncId
- 类型: <数字> 传递给
AsyncResource
构造函数的相同triggerAsyncId
。
EventTarget
和 Event
API
[历史]
版本 | 变更 |
---|---|
v16.0.0 | 更改了 EventTarget 错误处理。 |
v15.4.0 | 不再是实验性功能。 |
v15.0.0 | EventTarget 和 Event 类现在可用作全局变量。 |
v14.5.0 | 添加于:v14.5.0 |
EventTarget
和 Event
对象是 Node.js 特定的 EventTarget
Web API 实现,由一些 Node.js 核心 API 公开。
const target = new EventTarget()
target.addEventListener('foo', event => {
console.log('foo 事件发生了!')
})
Node.js EventTarget
与 DOM EventTarget
Node.js 的 EventTarget
和 EventTarget
Web API 之间存在两个主要区别:
NodeEventTarget
与 EventEmitter
NodeEventTarget
对象实现了 EventEmitter
API 的一个修改后的子集,使其能够在某些情况下模拟 EventEmitter
。NodeEventTarget
不是 EventEmitter
的实例,在大多数情况下不能替代 EventEmitter
。
事件监听器
为事件 type
注册的事件监听器可以是 JavaScript 函数,也可以是具有 handleEvent
属性的对象,该属性的值是一个函数。
在这两种情况下,处理程序函数都会使用传递给 eventTarget.dispatchEvent()
函数的 event
参数调用。
异步函数可以用作事件监听器。如果异步处理程序函数被拒绝,则会捕获并处理该拒绝,如EventTarget
错误处理中所述。
一个处理程序函数抛出的错误不会阻止其他处理程序被调用。
处理程序函数的返回值将被忽略。
处理程序始终按照添加它们的顺序调用。
处理程序函数可以修改 event
对象。
function handler1(event) {
console.log(event.type) // 打印 'foo'
event.a = 1
}
async function handler2(event) {
console.log(event.type) // 打印 'foo'
console.log(event.a) // 打印 1
}
const handler3 = {
handleEvent(event) {
console.log(event.type) // 打印 'foo'
},
}
const handler4 = {
async handleEvent(event) {
console.log(event.type) // 打印 '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('uncaughtException')
之前首先转发到 process.on('error')
事件。此行为已弃用,并在未来版本中将更改为使 EventTarget
与其他 Node.js API 保持一致。任何依赖 process.on('error')
事件的代码都应与新行为保持一致。
类: Event
[历史]
版本 | 变更 |
---|---|
v15.0.0 | Event 类现在可通过全局对象访问。 |
v14.5.0 | 新增于:v14.5.0 |
Event
对象是 Event
Web API 的一个适配器。实例由 Node.js 内部创建。
event.bubbles
新增于: v14.5.0
- 类型: <boolean> 始终返回
false
。
此属性在 Node.js 中未使用,仅为完整性而提供。
event.cancelBubble
新增于: v14.5.0
[稳定性: 3 - 已弃用]
稳定性: 3 稳定性: 3 - 已弃用: 请改用 event.stopPropagation()
。
- 类型: <boolean>
如果设置为 true
,则为 event.stopPropagation()
的别名。此属性在 Node.js 中未使用,仅为完整性而提供。
event.cancelable
新增于: v14.5.0
- 类型: <boolean> 如果事件是用
cancelable
选项创建的,则为true
。
event.composed
新增于: v14.5.0
- 类型: <boolean> 始终返回
false
。
此属性在 Node.js 中未使用,仅为完整性而提供。
event.composedPath()
新增于:v14.5.0
返回一个数组,其中包含当前的 EventTarget
作为唯一条目,如果事件未被分发则返回空数组。这在 Node.js 中未使用,仅为完整性而提供。
event.currentTarget
新增于:v14.5.0
- 类型:<EventTarget> 分发事件的
EventTarget
。
event.target
的别名。
event.defaultPrevented
新增于:v14.5.0
- 类型:<boolean>
如果 cancelable
为 true
并且调用了 event.preventDefault()
,则为 true
。
event.eventPhase
新增于:v14.5.0
- 类型:<number> 当事件未被分发时返回
0
,当事件正在被分发时返回2
。
这在 Node.js 中未使用,仅为完整性而提供。
event.initEvent(type[, bubbles[, cancelable]])
新增于:v19.5.0
与事件构造函数冗余,并且无法设置 composed
。这在 Node.js 中未使用,仅为完整性而提供。
event.isTrusted
新增于:v14.5.0
- 类型:<boolean>
<AbortSignal> "abort"
事件发出时,isTrusted
设置为 true
。在所有其他情况下,其值为 false
。
event.preventDefault()
新增于:v14.5.0
如果 cancelable
为 true
,则将 defaultPrevented
属性设置为 true
。
event.returnValue
新增于:v14.5.0
[稳定:3 - 遗留]
稳定:3 稳定性:3 - 遗留:请改用 event.defaultPrevented
。
- 类型:<boolean> 如果事件未被取消,则为
true
。
event.returnValue
的值始终与 event.defaultPrevented
相反。这在 Node.js 中未使用,仅出于完整性考虑而提供。
event.srcElement
新增于:v14.5.0
[稳定性:3 - 已弃用]
稳定性:3 稳定性:3 - 已弃用:请改用 event.target
。
- 类型:<EventTarget> 派发事件的
EventTarget
。
event.target
的别名。
event.stopImmediatePropagation()
新增于:v14.5.0
停止在当前事件监听器完成之后调用其他事件监听器。
event.stopPropagation()
新增于:v14.5.0
此方法在 Node.js 中未使用,仅为完整性而提供。
event.target
新增于:v14.5.0
- 类型:<EventTarget> 派发事件的
EventTarget
。
event.timeStamp
新增于:v14.5.0
- 类型:<number>
创建 Event
对象时的毫秒时间戳。
event.type
新增于:v14.5.0
- 类型:<string>
事件类型标识符。
类: EventTarget
[历史]
版本 | 变更 |
---|---|
v15.0.0 | EventTarget 类现在可通过全局对象访问。 |
v14.5.0 | 在 v14.5.0 中添加 |
eventTarget.addEventListener(type, listener[, options])
[历史]
版本 | 变更 |
---|---|
v15.4.0 | 添加对 signal 选项的支持。 |
v14.5.0 | 在 v14.5.0 中添加 |
type
<字符串>listener
<函数> | <事件监听器>options
<对象>once
<布尔值> 当值为true
时,监听器在第一次被调用时会自动移除。默认值:false
。passive
<布尔值> 当值为true
时,提示监听器不会调用Event
对象的preventDefault()
方法。默认值:false
。capture
<布尔值> 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 }) // 第一个
target.addEventListener('foo', handler, { capture: false }) // 第二个
// 移除第二个 handler 实例
target.removeEventListener('foo', handler)
// 移除第一个 handler 实例
target.removeEventListener('foo', handler, { capture: true })
eventTarget.dispatchEvent(event)
新增于: v14.5.0
event
<Event>- 返回值: <boolean> 如果事件的
cancelable
属性值为false
或其preventDefault()
方法未被调用,则返回true
,否则返回false
。
将 event
分派到 event.type
的处理程序列表。
已注册的事件监听器将按照注册顺序同步调用。
eventTarget.removeEventListener(type, listener[, options])
新增于: v14.5.0
type
<string>listener
<Function> | <EventListener>options
<Object>capture
<boolean>
从事件 type
的处理程序列表中移除 listener
。
类: CustomEvent
[历史]
版本 | 变更 |
---|---|
v23.0.0 | 不再是实验性功能。 |
v22.1.0, v20.13.0 | CustomEvent 现在稳定。 |
v19.0.0 | 不再需要 --experimental-global-customevent CLI 标记。 |
v18.7.0, v16.17.0 | 新增于:v18.7.0, v16.17.0 |
- 继承自: <Event>
CustomEvent
对象是对 CustomEvent
Web API 的改编。实例由 Node.js 内部创建。
event.detail
[历史]
版本 | 变更 |
---|---|
v22.1.0, v20.13.0 | CustomEvent 现在稳定。 |
v18.7.0, v16.17.0 | 新增于:v18.7.0, v16.17.0 |
- 类型: <any> 返回初始化时传递的自定义数据。
只读。
类: NodeEventTarget
新增于: v14.5.0
- 继承自: <EventTarget>
NodeEventTarget
是 EventTarget
的 Node.js 特定扩展,它模拟了 EventEmitter
API 的一个子集。
nodeEventTarget.addListener(type, listener)
新增于: v14.5.0
type
<string>listener
<Function> | <EventListener>- 返回: <EventTarget> this
Node.js 对 EventTarget
类的特定扩展,模拟了等效的 EventEmitter
API。addListener()
和 addEventListener()
之间的唯一区别在于 addListener()
将返回对 EventTarget
的引用。
nodeEventTarget.emit(type, arg)
新增于: v15.2.0
Node.js 对 EventTarget
类的特定扩展,它将 arg
分派给 type
的处理程序列表。
nodeEventTarget.eventNames()
新增于:v14.5.0
- 返回值:<string[]>
Node.js 对 EventTarget
类的特定扩展,返回已注册事件监听器的事件 type
名称数组。
nodeEventTarget.listenerCount(type)
新增于:v14.5.0
Node.js 对 EventTarget
类的特定扩展,返回为 type
注册的事件监听器数量。
nodeEventTarget.setMaxListeners(n)
新增于:v14.5.0
n
<number>
Node.js 对 EventTarget
类的特定扩展,将最大事件监听器数量设置为 n
。
nodeEventTarget.getMaxListeners()
新增于:v14.5.0
- 返回值: <number>
Node.js 对 EventTarget
类的特定扩展,返回最大事件监听器数量。
nodeEventTarget.off(type, listener[, options])
新增于:v14.5.0
type
<string>listener
<Function> | <EventListener>options
<Object>capture
<boolean>
返回值: <EventTarget> this
Node.js 对 eventTarget.removeEventListener()
的特定别名。
nodeEventTarget.on(type, listener)
新增于: v14.5.0
type
<string>listener
<Function> | <EventListener>- 返回: <EventTarget> this
eventTarget.addEventListener()
的 Node.js 专用别名。
nodeEventTarget.once(type, listener)
新增于: v14.5.0
type
<string>listener
<Function> | <EventListener>- 返回: <EventTarget> this
EventTarget
类的 Node.js 专用扩展,为给定的事件 type
添加一个 once
监听器。这等效于将 once
选项设置为 true
并调用 on
。
nodeEventTarget.removeAllListeners([type])
新增于:v14.5.0
type
<string>- 返回值:<EventTarget> this
Node.js 对 EventTarget
类的特定扩展。如果指定了 type
,则删除为 type
注册的所有监听器,否则删除所有注册的监听器。
nodeEventTarget.removeListener(type, listener[, options])
新增于:v14.5.0
type
<string>listener
<Function> | <EventListener>options
<Object>capture
<boolean>
返回值:<EventTarget> this
Node.js 对 EventTarget
类的特定扩展,用于删除给定 type
的 listener
。removeListener()
和 removeEventListener()
之间的唯一区别在于 removeListener()
将返回对 EventTarget
的引用。