События
[Стабильно: 2 - Стабильно]
Стабильно: 2 Стабильность: 2 - Стабильно
Исходный код: lib/events.js
Большая часть основного API Node.js построена на идиоматической асинхронной архитектуре, управляемой событиями, в которой определенные типы объектов (называемые "излучателями") испускают именованные события, вызывающие объекты 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('произошло событие!')
})
myEmitter.emit('event')
const EventEmitter = require('node:events')
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.on('event', () => {
console.log('произошло событие!')
})
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('ой!'))
// Выбрасывает ошибку и завершает работу Node.js
const EventEmitter = require('node:events')
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.emit('error', new Error('ой!'))
// Выбрасывает ошибку и завершает работу 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('ой! произошла ошибка')
})
myEmitter.emit('error', new Error('ой!'))
// Выводит: ой! произошла ошибка
const EventEmitter = require('node:events')
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.on('error', err => {
console.error('ой! произошла ошибка')
})
myEmitter.emit('error', new Error('ой!'))
// Выводит: ой! произошла ошибка
Возможно отслеживать события 'error'
без обработки испускаемой ошибки, установив прослушиватель с помощью символа events.errorMonitor
.
import { EventEmitter, errorMonitor } from 'node:events'
const myEmitter = new EventEmitter()
myEmitter.on(errorMonitor, err => {
MyMonitoringTool.log(err)
})
myEmitter.emit('error', new Error('ой!'))
// Все еще выбрасывает ошибку и завершает работу Node.js
const { EventEmitter, errorMonitor } = require('node:events')
const myEmitter = new EventEmitter()
myEmitter.on(errorMonitor, err => {
MyMonitoringTool.log(err)
})
myEmitter.emit('error', new Error('ой!'))
// Все еще выбрасывает ошибку и завершает работу Node.js
Захват отклонений промисов
Использование 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')
})
Опция captureRejections
в конструкторе EventEmitter
или глобальная настройка изменяют это поведение, устанавливая обработчик .then(undefined, handler)
на Promise
. Этот обработчик асинхронно направляет исключение в метод 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)
События 'error'
, генерируемые поведением captureRejections
, не имеют обработчика 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
<boolean> Он включает автоматический перехват отклонений промисов. По умолчанию:false
.
Событие: 'newListener'
Добавлено в: v0.1.26
eventName
<string> | <symbol> Имя события, на которое выполняется прослушиваниеlistener
<Function> Функция обработчика события
Экземпляр EventEmitter
сгенерирует свое собственное событие 'newListener'
перед добавлением слушателя в свой внутренний массив слушателей.
Слушателям, зарегистрированным для события 'newListener'
, передаются имя события и ссылка на добавляемого слушателя.
Тот факт, что событие срабатывает перед добавлением слушателя, имеет тонкий, но важный побочный эффект: любые дополнительные слушатели, зарегистрированные для того же name
внутри обратного вызова 'newListener'
, вставляются перед слушателем, который находится в процессе добавления.
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 |
eventName
<string> | <symbol> Имя событияlistener
<Function> Функция обработчика события
Событие 'removeListener'
испускается после удаления listener
.
emitter.addListener(eventName, listener)
Добавлено в: v0.1.26
eventName
<string> | <symbol>listener
<Function>
Псевдоним для 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
- Возвращает: <integer>
Возвращает текущее максимальное значение прослушивателей для EventEmitter
, которое устанавливается либо с помощью emitter.setMaxListeners(n)
, либо по умолчанию равно events.defaultMaxListeners
.
emitter.listenerCount(eventName[, listener])
[История]
Версия | Изменения |
---|---|
v19.8.0, v18.16.0 | Добавлен аргумент listener . |
v3.2.0 | Добавлено в: v3.2.0 |
eventName
<string> | <symbol> Имя события, которое прослушиваетсяlistener
<Function> Функция-обработчик события- Возвращает: <integer>
Возвращает количество прослушивателей, прослушивающих событие с именем eventName
. Если указан listener
, то возвращается количество раз, когда этот прослушиватель был найден в списке прослушивателей данного события.
emitter.listeners(eventName)
[История]
Версия | Изменения |
---|---|
v7.0.0 | Для слушателей, прикрепленных с помощью .once() , теперь возвращаются оригинальные слушатели, а не функции-обертки. |
v0.1.26 | Добавлено в: v0.1.26 |
eventName
<string> | <symbol>- Возвращает: <Function[]>
Возвращает копию массива слушателей для события с именем eventName
.
server.on('connection', stream => {
console.log('кто-то подключился!')
})
console.log(util.inspect(server.listeners('connection')))
// Выведет: [ [Function] ]
emitter.off(eventName, listener)
Добавлено в: v10.0.0
eventName
<string> | <symbol>listener
<Function>- Возвращает: <EventEmitter>
Псевдоним для emitter.removeListener()
.
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('кто-то подключился!')
})
Возвращает ссылку на 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>
Добавляет одноразовую функцию listener
для события с именем eventName
. При следующем срабатывании eventName
этот слушатель удаляется и затем вызывается.
server.once('connection', stream => {
console.log('А, у нас есть первый пользователь!')
})
Возвращает ссылку на 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('кто-то подключился!')
})
Возвращает ссылку на EventEmitter
, чтобы вызовы можно было объединять в цепочки.
emitter.prependOnceListener(eventName, listener)
Добавлено в: v6.0.0
eventName
<string> | <symbol> Имя события.listener
<Function> Функция обратного вызова- Возвращает: <EventEmitter>
Добавляет одноразовую функцию listener
для события с именем eventName
в начало массива слушателей. В следующий раз, когда событие eventName
будет вызвано, этот слушатель будет удален, а затем вызван.
server.prependOnceListener('connection', stream => {
console.log('Ага, у нас есть первый пользователь!')
})
Возвращает ссылку на EventEmitter
, чтобы вызовы можно было объединять в цепочку.
emitter.removeAllListeners([eventName])
Добавлено в: v0.1.26
eventName
<string> | <symbol>- Возвращает: <EventEmitter>
Удаляет все слушатели или слушатели указанного eventName
.
Удаление слушателей, добавленных в другом месте кода, является плохой практикой, особенно когда экземпляр EventEmitter
был создан другим компонентом или модулем (например, сокетами или файловыми потоками).
Возвращает ссылку на EventEmitter
, чтобы вызовы можно было объединять в цепочку.
emitter.removeListener(eventName, listener)
Добавлено в: v0.1.26
eventName
<string> | <symbol>listener
<Function>- Возвращает: <EventEmitter>
Удаляет указанный listener
из массива слушателей для события с именем eventName
.
const callback = stream => {
console.log('кто-то подключился!')
}
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
<integer>- Возвращает: <EventEmitter>
По умолчанию EventEmitter
выведет предупреждение, если для определенного события добавлено более 10
слушателей. Это полезное значение по умолчанию, которое помогает находить утечки памяти. Метод emitter.setMaxListeners()
позволяет изменить лимит для этого конкретного экземпляра EventEmitter
. Значение можно установить как Infinity
(или 0
), чтобы указать неограниченное количество слушателей.
Возвращает ссылку на EventEmitter
, чтобы вызовы можно было объединять в цепочку.
emitter.rawListeners(eventName)
Добавлено в: v9.4.0
eventName
<string> | <symbol>- Возвращает: <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 |
Метод Symbol.for('nodejs.rejection')
вызывается в случае, если происходит отклонение промиса при испускании события, и на испускателе включено свойство captureRejections
. Вместо Symbol.for('nodejs.rejection')
можно использовать events.captureRejectionSymbol
.
import { EventEmitter, captureRejectionSymbol } from 'node:events'
class MyClass extends EventEmitter {
constructor() {
super({ captureRejections: true })
}
[captureRejectionSymbol](err, event, ...args) {
console.log('отклонение произошло для', event, 'с', 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('отклонение произошло для', event, 'с', err, ...args)
this.destroy(err)
}
destroy(err) {
// Высвободить ресурс здесь.
}
}
events.defaultMaxListeners
Добавлено в: v0.11.2
По умолчанию для любого отдельного события можно зарегистрировать максимум 10
слушателей. Этот предел можно изменить для отдельных экземпляров EventEmitter
с помощью метода emitter.setMaxListeners(n)
. Чтобы изменить значение по умолчанию для всех экземпляров 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', () => {
// сделать что-то
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', () => {
// сделать что-то
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
испускает данное событие, или отклоняется, если EventEmitter
испускает 'error'
во время ожидания. 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()
Специальная обработка события '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'))
// Выводит: 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'))
// Выводит: 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() // Выводит: 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() // Выводит: 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 |
Значение: <boolean>
Изменяет опцию captureRejections
по умолчанию для всех новых объектов EventEmitter
.
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
<string> | <symbol> Имя события
Метод класса, который возвращает количество слушателей для данного eventName
, зарегистрированных на данном emitter
.
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>, который итерирует события
eventName
, излучаемыеemitter
.
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
[Стабильно: 1 - Экспериментально]
Стабильно: 1 Стабильность: 1 - Экспериментально
signal
<AbortSignal>listener
<Function> | <EventListener>- Возвращает: <Disposable> Disposable, который удаляет слушатель
abort
.
Один раз прослушивает событие abort
на предоставленном signal
.
Прослушивание события abort
на сигналах отмены небезопасно и может привести к утечкам ресурсов, поскольку другая третья сторона с сигналом может вызвать e.stopImmediatePropagation()
. К сожалению, Node.js не может это изменить, так как это нарушит веб-стандарт. Кроме того, исходный API позволяет легко забыть удалить слушателей.
Этот API позволяет безопасно использовать AbortSignal
в API Node.js, решая эти две проблемы, прослушивая событие таким образом, чтобы 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' будут выполняться в асинхронном контексте EventEmitters.
ee1.on('foo', () => {
strictEqual(executionAsyncId(), ee1.asyncId)
strictEqual(triggerAsyncId(), ee1.triggerAsyncId)
})
const ee2 = new EventEmitter()
// Слушатели 'foo' в обычных EventEmitters, которые не отслеживают асинхронный
// контекст, тем не менее, выполняются в том же асинхронном контексте, что и 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' будут выполняться в асинхронном контексте EventEmitters.
ee1.on('foo', () => {
strictEqual(executionAsyncId(), ee1.asyncId)
strictEqual(triggerAsyncId(), ee1.triggerAsyncId)
})
const ee2 = new EventEmitter()
// Слушатели 'foo' в обычных EventEmitters, которые не отслеживают асинхронный
// контекст, тем не менее, выполняются в том же асинхронном контексте, что и 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
ресурса и чувствительный APIemitDestroy
не вызывается с ним. Если установлено значениеfalse
, вызовemitDestroy
при сборке мусора произойдет только в том случае, если есть хотя бы один активный хукdestroy
. По умолчанию:false
.
eventemitterasyncresource.asyncId
- Тип: <number> Уникальный
asyncId
, назначенный ресурсу.
eventemitterasyncresource.asyncResource
- Тип: Базовый <AsyncResource>.
Возвращенный объект AsyncResource
имеет дополнительное свойство eventEmitter
, которое предоставляет ссылку на этот EventEmitterAsyncResource
.
eventemitterasyncresource.emitDestroy()
Вызывает все хуки destroy
. Это должно вызываться только один раз. Если это будет вызвано более одного раза, будет выдана ошибка. Это должно быть вызвано вручную. Если ресурс оставлен для сборки GC, то хуки destroy
никогда не будут вызваны.
eventemitterasyncresource.triggerAsyncId
- Type: <number> The same
triggerAsyncId
that is passed to theAsyncResource
constructor.
EventTarget
and 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, которые предоставляются некоторыми основными API Node.js.
const target = new EventTarget()
target.addEventListener('foo', event => {
console.log('foo event happened!')
})
Node.js EventTarget
vs. DOM EventTarget
Существует два ключевых различия между Node.js EventTarget
и EventTarget
Web API:
NodeEventTarget
vs. EventEmitter
Объект NodeEventTarget
реализует модифицированное подмножество API EventEmitter
, которое позволяет ему тесно имитировать EventEmitter
в определенных ситуациях. NodeEventTarget
не является экземпляром EventEmitter
и не может быть использован вместо EventEmitter
в большинстве случаев.
Обработчик событий
Обработчики событий, зарегистрированные для события type
, могут быть либо JavaScript-функциями, либо объектами со свойством handleEvent
, значением которого является функция.
В любом случае функция-обработчик вызывается с аргументом event
, переданным в функцию eventTarget.dispatchEvent()
.
Асинхронные функции могут использоваться в качестве обработчиков событий. Если асинхронная функция-обработчик отклоняет, отклонение перехватывается и обрабатывается, как описано в разделе EventTarget
error handling.
Ошибка, выброшенная одной функцией-обработчиком, не мешает вызову других обработчиков.
Возвращаемое значение функции-обработчика игнорируется.
Обработчики всегда вызываются в порядке их добавления.
Функции-обработчики могут изменять объект 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
не реализует какую-либо специальную обработку по умолчанию для событий типа 'error'
, как EventEmitter
.
В настоящее время ошибки сначала перенаправляются в событие process.on('error')
, прежде чем достичь process.on('uncaughtException')
. Это поведение является устаревшим и изменится в будущем выпуске, чтобы привести EventTarget
в соответствие с другими API Node.js. Любой код, зависящий от события 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>
Псевдоним для event.stopPropagation()
, если установлено значение true
. Это не используется в Node.js и предоставляется исключительно для полноты картины.
event.cancelable
Добавлено в: v14.5.0
- Тип: <boolean> True, если событие было создано с опцией
cancelable
.
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>
Имеет значение true
, если cancelable
имеет значение true
, и был вызван метод event.preventDefault()
.
event.eventPhase
Добавлено в: v14.5.0
- Тип: <number> Возвращает
0
, пока событие не отправляется,2
, пока оно отправляется.
Это не используется в Node.js и предоставляется исключительно для полноты картины.
event.initEvent(type[, bubbles[, cancelable]])
Добавлено в: v19.5.0
[Stable: 3 - Legacy]
Stable: 3 Стабильность: 3 - Устаревшее: спецификация WHATWG считает его устаревшим, и пользователям не следует его использовать.
Избыточно с конструкторами событий и неспособно устанавливать composed
. Это не используется в Node.js и предоставляется исключительно для полноты картины.
event.isTrusted
Добавлено в: v14.5.0
- Тип: <boolean>
Событие "abort"
<AbortSignal> отправляется со значением isTrusted
, установленным в true
. В остальных случаях значение равно false
.
event.preventDefault()
Добавлено в: v14.5.0
Устанавливает свойство defaultPrevented
в true
, если cancelable
равно 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
<string>listener
<Function> | <EventListener>options
<Object>once
<boolean> Еслиtrue
, то слушатель автоматически удаляется при первом вызове. По умолчанию:false
.passive
<boolean> Еслиtrue
, служит подсказкой, что слушатель не будет вызывать методpreventDefault()
объектаEvent
. По умолчанию:false
.capture
<boolean> Не используется Node.js напрямую. Добавлено для полноты API. По умолчанию:false
.signal
<AbortSignal> Слушатель будет удален, когда будет вызван методabort()
заданного объекта AbortSignal.
Добавляет новый обработчик для события type
. Любой заданный listener
добавляется только один раз для каждого type
и значения параметра capture
.
Если параметр once
имеет значение true
, то listener
удаляется после следующего возникновения события type
.
Параметр 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 }) // второй
// Удаляет второй экземпляр обработчика
target.removeEventListener('foo', handler)
// Удаляет первый экземпляр обработчика
target.removeEventListener('foo', handler, { capture: true })
eventTarget.dispatchEvent(event)
Добавлено в: v14.5.0
event
<Event>- Возвращает: <boolean>
true
, если либо атрибутcancelable
события имеет значение false, либо его методpreventDefault()
не был вызван, в противном случаеfalse
.
Отправляет event
списку обработчиков для event.type
.
Зарегистрированные прослушиватели событий вызываются синхронно в том порядке, в котором они были зарегистрированы.
eventTarget.removeEventListener(type, listener[, options])
Добавлено в: v14.5.0
type
<string>listener
<Function> | <EventListener>options
<Object>capture
<boolean>
Удаляет listener
из списка обработчиков для события type
.
Class: CustomEvent
[История]
Версия | Изменения |
---|---|
v23.0.0 | Больше не является экспериментальным. |
v22.1.0, v20.13.0 | CustomEvent теперь стабилен. |
v19.0.0 | Больше не скрывается за флагом CLI --experimental-global-customevent . |
v18.7.0, v16.17.0 | Добавлено в: v18.7.0, v16.17.0 |
[Стабильно: 2 - Стабильно]
Стабильно: 2 Стабильность: 2 - Стабильно
- Расширяет: <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 |
[Стабильно: 2 - Стабильно]
Стабильно: 2 Стабильность: 2 - Стабильно
- Тип: <any> Возвращает пользовательские данные, переданные при инициализации.
Только для чтения.
Класс: NodeEventTarget
Добавлено в: v14.5.0
- Расширяет: <EventTarget>
NodeEventTarget
является специфичным для Node.js расширением EventTarget
, которое эмулирует подмножество API EventEmitter
.
nodeEventTarget.addListener(type, listener)
Добавлено в: v14.5.0
type
<string>listener
<Function> | <EventListener>- Возвращает: <EventTarget> this
Специфичное для Node.js расширение класса EventTarget
, которое эмулирует эквивалентный API EventEmitter
. Единственное отличие между addListener()
и addEventListener()
заключается в том, что addListener()
вернет ссылку на EventTarget
.
nodeEventTarget.emit(type, arg)
Добавлено в: v15.2.0
type
<string>arg
<any>- Возвращает: <boolean>
true
, если существуют прослушиватели событий, зарегистрированные дляtype
, иначеfalse
.
Специфичное для 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
Node.js-специфичный псевдоним для eventTarget.addEventListener()
.
nodeEventTarget.once(type, listener)
Добавлено в: v14.5.0
type
<string>listener
<Function> | <EventListener>- Возвращает: <EventTarget> this
Node.js-специфичное расширение класса EventTarget
, которое добавляет прослушиватель once
для заданного события type
. Это эквивалентно вызову on
с опцией once
, установленной в true
.
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
, которое удаляет listener
для заданного type
. Единственное отличие между removeListener()
и removeEventListener()
заключается в том, что removeListener()
возвращает ссылку на EventTarget
.