Skip to content

События

[Стабильно: 2 - Стабильно]

Стабильно: 2 Стабильность: 2 - Стабильно

Исходный код: lib/events.js

Большая часть основного API Node.js построена на идиоматической асинхронной архитектуре, управляемой событиями, в которой определенные типы объектов (называемые "излучателями") испускают именованные события, вызывающие объекты Function ("слушатели").

Например: объект net.Server испускает событие каждый раз, когда к нему подключается пир; fs.ReadStream испускает событие при открытии файла; поток испускает событие всякий раз, когда доступны данные для чтения.

Все объекты, испускающие события, являются экземплярами класса EventEmitter. Эти объекты предоставляют функцию eventEmitter.on(), которая позволяет привязывать одну или несколько функций к именованным событиям, испускаемым объектом. Обычно имена событий являются строками в верблюжьем регистре, но можно использовать любой допустимый ключ свойства JavaScript.

Когда объект EventEmitter испускает событие, все функции, привязанные к этому конкретному событию, вызываются синхронно. Любые значения, возвращаемые вызванными слушателями, игнорируются и отбрасываются.

В следующем примере показан простой экземпляр EventEmitter с одним слушателем. Метод eventEmitter.on() используется для регистрации слушателей, а метод eventEmitter.emit() используется для запуска события.

js
import { EventEmitter } from 'node:events'

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter()
myEmitter.on('event', () => {
  console.log('произошло событие!')
})
myEmitter.emit('event')
js
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, к которому привязан слушатель.

js
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')
js
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:

js
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')
js
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():

js
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')
js
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(), этот слушатель вызывается каждый раз, когда происходит событие с указанным именем.

js
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
js
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(), можно зарегистрировать слушателя, который будет вызван не более одного раза для определенного события. После того, как событие произошло, слушатель отменяется, а затем вызывается.

js
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')
// Игнорируется
js
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 завершается.

js
import { EventEmitter } from 'node:events'
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.emit('error', new Error('ой!'))
// Выбрасывает ошибку и завершает работу Node.js
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'.

js
import { EventEmitter } from 'node:events'
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter()
myEmitter.on('error', err => {
  console.error('ой! произошла ошибка')
})
myEmitter.emit('error', new Error('ой!'))
// Выводит: ой! произошла ошибка
js
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.

js
import { EventEmitter, errorMonitor } from 'node:events'

const myEmitter = new EventEmitter()
myEmitter.on(errorMonitor, err => {
  MyMonitoringTool.log(err)
})
myEmitter.emit('error', new Error('ой!'))
// Все еще выбрасывает ошибку и завершает работу Node.js
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 функций с обработчиками событий является проблематичным, поскольку это может привести к необработанному отклонению в случае выброшенного исключения:

js
import { EventEmitter } from 'node:events'
const ee = new EventEmitter()
ee.on('something', async value => {
  throw new Error('kaboom')
})
js
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', если его нет.

js
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
js
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.

js
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)
js
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:

js
import { EventEmitter } from 'node:events'
js
const EventEmitter = require('node:events')

Все EventEmitter генерируют событие 'newListener', когда добавляются новые слушатели, и 'removeListener', когда существующие слушатели удаляются.

Он поддерживает следующие параметры:

Событие: 'newListener'

Добавлено в: v0.1.26

  • eventName <string> | <symbol> Имя события, на которое выполняется прослушивание
  • listener <Function> Функция обработчика события

Экземпляр EventEmitter сгенерирует свое собственное событие 'newListener' перед добавлением слушателя в свой внутренний массив слушателей.

Слушателям, зарегистрированным для события 'newListener', передаются имя события и ссылка на добавляемого слушателя.

Тот факт, что событие срабатывает перед добавлением слушателя, имеет тонкий, но важный побочный эффект: любые дополнительные слушатели, зарегистрированные для того же name внутри обратного вызова 'newListener', вставляются перед слушателем, который находится в процессе добавления.

js
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
js
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 в противном случае.

js
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
js
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

Возвращает массив, перечисляющий события, для которых эмиттер зарегистрировал прослушиватели. Значения в массиве являются строками или Symbol.

js
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) ]
js
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

Возвращает текущее максимальное значение прослушивателей для 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.

js
server.on('connection', stream => {
  console.log('кто-то подключился!')
})
console.log(util.inspect(server.listeners('connection')))
// Выведет: [ [Function] ]

emitter.off(eventName, listener)

Добавлено в: v10.0.0

Псевдоним для emitter.removeListener().

emitter.on(eventName, listener)

Добавлено в: v0.1.101

Добавляет функцию listener в конец массива слушателей для события с именем eventName. Никаких проверок на то, был ли уже добавлен listener, не производится. Множественные вызовы с одной и той же комбинацией eventName и listener приведут к тому, что listener будет добавлен и вызван несколько раз.

js
server.on('connection', stream => {
  console.log('кто-то подключился!')
})

Возвращает ссылку на EventEmitter, чтобы вызовы можно было связать в цепочку.

По умолчанию, обработчики событий вызываются в том порядке, в котором они были добавлены. Метод emitter.prependListener() можно использовать в качестве альтернативы для добавления обработчика событий в начало массива слушателей.

js
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
js
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

Добавляет одноразовую функцию listener для события с именем eventName. При следующем срабатывании eventName этот слушатель удаляется и затем вызывается.

js
server.once('connection', stream => {
  console.log('А, у нас есть первый пользователь!')
})

Возвращает ссылку на EventEmitter, чтобы вызовы можно было объединять в цепочки.

По умолчанию, прослушиватели событий вызываются в порядке их добавления. Метод emitter.prependOnceListener() можно использовать в качестве альтернативы для добавления прослушивателя событий в начало массива прослушивателей.

js
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
js
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

Добавляет функцию listener в начало массива прослушивателей для события с именем eventName. Не производится никаких проверок на то, был ли уже добавлен listener. Многократные вызовы с передачей одной и той же комбинации eventName и listener приведут к тому, что listener будет добавлен и вызван несколько раз.

js
server.prependListener('connection', stream => {
  console.log('кто-то подключился!')
})

Возвращает ссылку на EventEmitter, чтобы вызовы можно было объединять в цепочки.

emitter.prependOnceListener(eventName, listener)

Добавлено в: v6.0.0

Добавляет одноразовую функцию listener для события с именем eventName в начало массива слушателей. В следующий раз, когда событие eventName будет вызвано, этот слушатель будет удален, а затем вызван.

js
server.prependOnceListener('connection', stream => {
  console.log('Ага, у нас есть первый пользователь!')
})

Возвращает ссылку на EventEmitter, чтобы вызовы можно было объединять в цепочку.

emitter.removeAllListeners([eventName])

Добавлено в: v0.1.26

Удаляет все слушатели или слушатели указанного eventName.

Удаление слушателей, добавленных в другом месте кода, является плохой практикой, особенно когда экземпляр EventEmitter был создан другим компонентом или модулем (например, сокетами или файловыми потоками).

Возвращает ссылку на EventEmitter, чтобы вызовы можно было объединять в цепочку.

emitter.removeListener(eventName, listener)

Добавлено в: v0.1.26

Удаляет указанный listener из массива слушателей для события с именем eventName.

js
const callback = stream => {
  console.log('кто-то подключился!')
}
server.on('connection', callback)
// ...
server.removeListener('connection', callback)

removeListener() удалит не более одного экземпляра слушателя из массива слушателей. Если какой-либо отдельный слушатель был добавлен несколько раз в массив слушателей для указанного eventName, то removeListener() должен быть вызван несколько раз для удаления каждого экземпляра.

После того как событие испущено, все слушатели, привязанные к нему на момент испускания, вызываются по порядку. Это означает, что любые вызовы removeListener() или removeAllListeners() после испускания и до завершения выполнения последнего слушателя не удалят их из выполняющегося emit(). Последующие события ведут себя как ожидается.

js
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
js
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'):

js
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')
js
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

По умолчанию EventEmitter выведет предупреждение, если для определенного события добавлено более 10 слушателей. Это полезное значение по умолчанию, которое помогает находить утечки памяти. Метод emitter.setMaxListeners() позволяет изменить лимит для этого конкретного экземпляра EventEmitter. Значение можно установить как Infinity (или 0), чтобы указать неограниченное количество слушателей.

Возвращает ссылку на EventEmitter, чтобы вызовы можно было объединять в цепочку.

emitter.rawListeners(eventName)

Добавлено в: v9.4.0

Возвращает копию массива слушателей для события с именем eventName, включая любые обертки (например, созданные с помощью .once()).

js
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')
js
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.

js
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) {
    // Высвободить ресурс здесь.
  }
}
js
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 не будут выдавать предупреждения.

js
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))
})
js
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

Возвращает копию массива слушателей для события с именем eventName.

Для EventEmitter это ведет себя точно так же, как вызов .listeners у эмиттера.

Для EventTarget это единственный способ получить слушателей событий для целевого события. Это полезно для отладки и диагностики.

js
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] ]
}
js
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

Возвращает текущее установленное максимальное количество слушателей.

Для EventEmitter это работает точно так же, как и вызов .getMaxListeners на эмиттере.

Для EventTarget это единственный способ получить максимальное количество слушателей событий для целевого события. Если количество обработчиков событий для одного EventTarget превышает установленный максимум, EventTarget выведет предупреждение.

js
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
}
js
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

Создает Promise, который выполняется, когда EventEmitter испускает данное событие, или отклоняется, если EventEmitter испускает 'error' во время ожидания. Promise будет разрешен с массивом всех аргументов, испускаемых в данное событие.

Этот метод намеренно является общим и работает с веб-платформой интерфейсом EventTarget, который не имеет специальной семантики события 'error' и не прослушивает событие 'error'.

js
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)
}
js
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', тогда оно обрабатывается как любой другой вид события без специальной обработки:

js
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
js
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> можно использовать для отмены ожидания события:

js
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!
js
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() пропустит событие.

js
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'))
js
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():

js
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'))
js
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() вместо этого.

Метод класса, который возвращает количество слушателей для данного eventName, зарегистрированных на данном emitter.

js
import { EventEmitter, listenerCount } from 'node:events'

const myEmitter = new EventEmitter()
myEmitter.on('event', () => {})
myEmitter.on('event', () => {})
console.log(listenerCount(myEmitter, 'event'))
// Выводит: 2
js
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>

  • eventName <string> | <symbol> Имя прослушиваемого события.

  • options <Object>

    • signal <AbortSignal> Может использоваться для отмены ожидания событий.
    • close - <string[]> Имена событий, которые завершат итерацию.
    • highWaterMark - <integer> По умолчанию: Number.MAX_SAFE_INTEGER Верхняя граница. Излучатель приостанавливается каждый раз, когда размер буферизуемых событий становится выше этой границы. Поддерживается только для излучателей, реализующих методы pause() и resume().
    • lowWaterMark - <integer> По умолчанию: 1 Нижняя граница. Излучатель возобновляется каждый раз, когда размер буферизуемых событий становится ниже этой границы. Поддерживается только для излучателей, реализующих методы pause() и resume().
  • Возвращает: <AsyncIterator>, который итерирует события eventName, излучаемые emitter.

js
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]
}
// Недостижимо здесь
js
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> может использоваться для отмены ожидания событий:

js
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())
js
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>.
js
import { setMaxListeners, EventEmitter } from 'node:events'

const target = new EventTarget()
const emitter = new EventEmitter()

setMaxListeners(5, target, emitter)
js
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 - Экспериментально

Один раз прослушивает событие abort на предоставленном signal.

Прослушивание события abort на сигналах отмены небезопасно и может привести к утечкам ресурсов, поскольку другая третья сторона с сигналом может вызвать e.stopImmediatePropagation(). К сожалению, Node.js не может это изменить, так как это нарушит веб-стандарт. Кроме того, исходный API позволяет легко забыть удалить слушателей.

Этот API позволяет безопасно использовать AbortSignal в API Node.js, решая эти две проблемы, прослушивая событие таким образом, чтобы stopImmediatePropagation не мешал запуску слушателя.

Возвращает Disposable, чтобы от него можно было легче отписаться.

js
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]()
  }
}
js
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, будут выполняться в их асинхронном контексте.

js
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')
})
js
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 ресурса и чувствительный API emitDestroy не вызывается с ним. Если установлено значение false, вызов emitDestroy при сборке мусора произойдет только в том случае, если есть хотя бы один активный хук destroy. По умолчанию: false.

eventemitterasyncresource.asyncId

  • Тип: <number> Уникальный asyncId, назначенный ресурсу.

eventemitterasyncresource.asyncResource

Возвращенный объект AsyncResource имеет дополнительное свойство eventEmitter, которое предоставляет ссылку на этот EventEmitterAsyncResource.

eventemitterasyncresource.emitDestroy()

Вызывает все хуки destroy. Это должно вызываться только один раз. Если это будет вызвано более одного раза, будет выдана ошибка. Это должно быть вызвано вручную. Если ресурс оставлен для сборки GC, то хуки destroy никогда не будут вызваны.

eventemitterasyncresource.triggerAsyncId

  • Type: <number> The same triggerAsyncId that is passed to the AsyncResource 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.

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.

js
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().

Псевдоним для 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

Имеет значение 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

Событие "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

Метка времени в миллисекундах, когда был создан объект Event.

event.type

Добавлено в: v14.5.0

Идентификатор типа события.

Класс: 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.

js
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

Удаляет listener из списка обработчиков для события type.

Class: CustomEvent

[История]

ВерсияИзменения
v23.0.0Больше не является экспериментальным.
v22.1.0, v20.13.0CustomEvent теперь стабилен.
v19.0.0Больше не скрывается за флагом CLI --experimental-global-customevent.
v18.7.0, v16.17.0Добавлено в: v18.7.0, v16.17.0

[Стабильно: 2 - Стабильно]

Стабильно: 2 Стабильность: 2 - Стабильно

Объект CustomEvent является адаптацией CustomEvent Web API. Экземпляры создаются внутри Node.js.

event.detail

[История]

ВерсияИзменения
v22.1.0, v20.13.0CustomEvent теперь стабилен.
v18.7.0, v16.17.0Добавлено в: v18.7.0, v16.17.0

[Стабильно: 2 - Стабильно]

Стабильно: 2 Стабильность: 2 - Стабильно

  • Тип: <any> Возвращает пользовательские данные, переданные при инициализации.

Только для чтения.

Класс: NodeEventTarget

Добавлено в: v14.5.0

NodeEventTarget является специфичным для Node.js расширением EventTarget, которое эмулирует подмножество API EventEmitter.

nodeEventTarget.addListener(type, listener)

Добавлено в: v14.5.0

Специфичное для 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

Специфичное для Node.js расширение класса EventTarget, которое возвращает массив имен type событий, для которых зарегистрированы прослушиватели событий.

nodeEventTarget.listenerCount(type)

Добавлено в: v14.5.0

Специфичное для Node.js расширение класса EventTarget, которое возвращает количество прослушивателей событий, зарегистрированных для type.

nodeEventTarget.setMaxListeners(n)

Добавлено в: v14.5.0

Node.js-специфичное расширение класса EventTarget, которое устанавливает максимальное количество прослушивателей событий равным n.

nodeEventTarget.getMaxListeners()

Добавлено в: v14.5.0

Node.js-специфичное расширение класса EventTarget, которое возвращает максимальное количество прослушивателей событий.

nodeEventTarget.off(type, listener[, options])

Добавлено в: v14.5.0

Node.js-специфичный псевдоним для eventTarget.removeEventListener().

nodeEventTarget.on(type, listener)

Добавлено в: v14.5.0

Node.js-специфичный псевдоним для eventTarget.addEventListener().

nodeEventTarget.once(type, listener)

Добавлено в: v14.5.0

Node.js-специфичное расширение класса EventTarget, которое добавляет прослушиватель once для заданного события type. Это эквивалентно вызову on с опцией once, установленной в true.

nodeEventTarget.removeAllListeners([type])

Добавлено в: v14.5.0

Специфичное для Node.js расширение класса EventTarget. Если type указан, удаляет все зарегистрированные слушатели для type, в противном случае удаляет все зарегистрированные слушатели.

nodeEventTarget.removeListener(type, listener[, options])

Добавлено в: v14.5.0

Специфичное для Node.js расширение класса EventTarget, которое удаляет listener для заданного type. Единственное отличие между removeListener() и removeEventListener() заключается в том, что removeListener() возвращает ссылку на EventTarget.