Spec-Zone.ru › Node.js 24 LTS

События

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

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

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

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

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

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

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

Модули JavaScript
import { EventEmitter } from 'node:events';

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
  console.log('an event occurred!');
});
myEmitter.emit('event');
CommonJS
const EventEmitter = require('node:events');

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
  console.log('an event occurred!');
});
myEmitter.emit('event');

Передача аргументов и this обработчикам

Метод eventEmitter.emit() позволяет передать обработчикам произвольный набор аргументов. Обратите внимание: при вызове обычной функции-обработчика стандартное ключевое слово this намеренно устанавливается так, чтобы ссылаться на экземпляр EventEmitter, к которому привязан обработчик.

Модули JavaScript
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', function(a, b) {
  console.log(a, b, this, this === myEmitter);
  // Prints:
  //   a b MyEmitter {
  //     _events: [Object: null prototype] { event: [Function (anonymous)] },
  //     _eventsCount: 1,
  //     _maxListeners: undefined,
  //     Symbol(shapeMode): false,
  //     Symbol(kCapture): false
  //   } true
});
myEmitter.emit('event', 'a', 'b');
CommonJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', function(a, b) {
  console.log(a, b, this, this === myEmitter);
  // Prints:
  //   a b MyEmitter {
  //     _events: [Object: null prototype] { event: [Function (anonymous)] },
  //     _eventsCount: 1,
  //     _maxListeners: undefined,
  //     Symbol(shapeMode): false,
  //     Symbol(kCapture): false
  //   } true
});
myEmitter.emit('event', 'a', 'b');

В качестве обработчиков можно использовать стрелочные функции ES6, однако в этом случае ключевое слово this больше не будет ссылаться на экземпляр EventEmitter:

Модули JavaScript
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
  console.log(a, b, this);
  // Prints: a b undefined
});
myEmitter.emit('event', 'a', 'b');
CommonJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
  console.log(a, b, this);
  // Prints: a b {}
});
myEmitter.emit('event', 'a', 'b');

Асинхронное и синхронное выполнение

Объект EventEmitter вызывает все обработчики синхронно, в порядке их регистрации. Это обеспечивает правильную последовательность событий и помогает избежать гонок и логических ошибок. При необходимости функции-обработчики могут переключиться на асинхронный режим работы с помощью методов setImmediate() или process.nextTick():

Модули JavaScript
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');
CommonJS
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(), он вызывается каждый раз, когда генерируется именованное событие.

Модули JavaScript
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.on('event', () => {
  console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Prints: 2
CommonJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.on('event', () => {
  console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Prints: 2

С помощью метода eventEmitter.once() можно зарегистрировать обработчик, который будет вызван для определённого события не более одного раза. После генерации события обработчик удаляется из регистрации и затем вызывается.

Модули JavaScript
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.once('event', () => {
  console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Ignored
CommonJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.once('event', () => {
  console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Ignored

События ошибок

При возникновении ошибки в экземпляре EventEmitter обычно генерируется событие 'error'. В Node.js такие события обрабатываются особым образом.

Если для объекта EventEmitter не зарегистрирован хотя бы один обработчик события 'error' и генерируется событие 'error', ошибка выбрасывается, выводится трассировка стека, и процесс Node.js завершается.

Модули JavaScript
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// Throws and crashes Node.js
CommonJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// Throws and crashes Node.js

Чтобы предотвратить аварийное завершение процесса Node.js, можно использовать модуль domain. (Однако обратите внимание, что модуль node:domain объявлен устаревшим.)

Рекомендуется всегда добавлять обработчики для событий 'error'.

Модули JavaScript
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('error', (err) => {
  console.error('whoops! there was an error');
});
myEmitter.emit('error', new Error('whoops!'));
// Prints: whoops! there was an error
CommonJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('error', (err) => {
  console.error('whoops! there was an error');
});
myEmitter.emit('error', new Error('whoops!'));
// Prints: whoops! there was an error

Можно отслеживать события 'error', не поглощая генерируемую ошибку, установив обработчик с помощью символа events.errorMonitor.

Модули JavaScript
import { EventEmitter, errorMonitor } from 'node:events';

const myEmitter = new EventEmitter();
myEmitter.on(errorMonitor, (err) => {
  MyMonitoringTool.log(err);
});
myEmitter.emit('error', new Error('whoops!'));
// Still throws and crashes Node.js
CommonJS
const { EventEmitter, errorMonitor } = require('node:events');

const myEmitter = new EventEmitter();
myEmitter.on(errorMonitor, (err) => {
  MyMonitoringTool.log(err);
});
myEmitter.emit('error', new Error('whoops!'));
// Still throws and crashes Node.js

Перехват отклонённых промисов

Использование функций async в обработчиках событий может привести к проблемам, поскольку в случае выброшенного исключения это может вызвать необработанное отклонение промиса:

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

Модули JavaScript
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;
CommonJS
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.

Модули JavaScript
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);
CommonJS
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, нет обработчика перехвата, чтобы избежать бесконечных циклов ошибок. Поэтому рекомендуется не использовать функции async в качестве обработчиков событий 'error'.

Класс: EventEmitter

История
Версия Изменения
v13.4.0, v12.16.0

Добавлен параметр captureRejections.

v0.1.26

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

Класс EventEmitter определён и экспортируется модулем node:events:

Модули JavaScript
import { EventEmitter } from 'node:events';
CommonJS
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', вставляются перед обработчиком, который в данный момент добавляется.

Модули JavaScript
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
// Only do this once so we don't loop forever
myEmitter.once('newListener', (event, listener) => {
  if (event === 'event') {
    // Insert a new listener in front
    myEmitter.on('event', () => {
      console.log('B');
    });
  }
});
myEmitter.on('event', () => {
  console.log('A');
});
myEmitter.emit('event');
// Prints:
//   B
//   A
CommonJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();
// Only do this once so we don't loop forever
myEmitter.once('newListener', (event, listener) => {
  if (event === 'event') {
    // Insert a new listener in front
    myEmitter.on('event', () => {
      console.log('B');
    });
  }
});
myEmitter.on('event', () => {
  console.log('A');
});
myEmitter.emit('event');
// Prints:
//   B
//   A

Событие: 'removeListener'

История
Версия Изменения
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 <string> | <symbol>
  • ...args <any>
  • Возвращает: <boolean>

Синхронно вызывает все обработчики, зарегистрированные для события с именем eventName, в порядке их регистрации, передавая каждому из них указанные аргументы.

Возвращает true, если у события были обработчики, и false в противном случае.

Модули JavaScript
import { EventEmitter } from 'node:events';
const myEmitter = new EventEmitter();

// First listener
myEmitter.on('event', function firstListener() {
  console.log('Helloooo! first listener');
});
// Second listener
myEmitter.on('event', function secondListener(arg1, arg2) {
  console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
});
// Third listener
myEmitter.on('event', function thirdListener(...args) {
  const parameters = args.join(', ');
  console.log(`event with parameters ${parameters} in third listener`);
});

console.log(myEmitter.listeners('event'));

myEmitter.emit('event', 1, 2, 3, 4, 5);

// Prints:
// [
//   [Function: firstListener],
//   [Function: secondListener],
//   [Function: thirdListener]
// ]
// Helloooo! first listener
// event with parameters 1, 2 in second listener
// event with parameters 1, 2, 3, 4, 5 in third listener
CommonJS
const EventEmitter = require('node:events');
const myEmitter = new EventEmitter();

// First listener
myEmitter.on('event', function firstListener() {
  console.log('Helloooo! first listener');
});
// Second listener
myEmitter.on('event', function secondListener(arg1, arg2) {
  console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
});
// Third listener
myEmitter.on('event', function thirdListener(...args) {
  const parameters = args.join(', ');
  console.log(`event with parameters ${parameters} in third listener`);
});

console.log(myEmitter.listeners('event'));

myEmitter.emit('event', 1, 2, 3, 4, 5);

// Prints:
// [
//   [Function: firstListener],
//   [Function: secondListener],
//   [Function: thirdListener]
// ]
// Helloooo! first listener
// event with parameters 1, 2 in second listener
// event with parameters 1, 2, 3, 4, 5 in third listener

emitter.eventNames()

Добавлено в: v6.0.0
  • Возвращает: <string[]> | <symbol[]>

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

Модули JavaScript
import { EventEmitter } from 'node:events';

const myEE = new EventEmitter();
myEE.on('foo', () => {});
myEE.on('bar', () => {});

const sym = Symbol('symbol');
myEE.on(sym, () => {});

console.log(myEE.eventNames());
// Prints: [ 'foo', 'bar', Symbol(symbol) ]
CommonJS
const EventEmitter = require('node:events');

const myEE = new EventEmitter();
myEE.on('foo', () => {});
myEE.on('bar', () => {});

const sym = Symbol('symbol');
myEE.on(sym, () => {});

console.log(myEE.eventNames());
// Prints: [ 'foo', 'bar', Symbol(symbol) ]

emitter.getMaxListeners()

Добавлено в: 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('someone connected!');
});
console.log(util.inspect(server.listeners('connection')));
// Prints: [ [Function] ] copy

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('someone connected!');
}); copy

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

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

Модули JavaScript
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
//   b
//   a
CommonJS
const EventEmitter = require('node:events');
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
//   b
//   a

emitter.once(eventName, listener)

Добавлено в: v0.3.0
  • eventName <string> | <symbol> Имя события.
  • listener <Function> Функция обратного вызова
  • Возвращает: <EventEmitter>

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

server.once('connection', (stream) => {
  console.log('Ah, we have our first user!');
}); copy

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

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

Модули JavaScript
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.once('foo', () => console.log('a'));
myEE.prependOnceListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
//   b
//   a
CommonJS
const EventEmitter = require('node:events');
const myEE = new EventEmitter();
myEE.once('foo', () => console.log('a'));
myEE.prependOnceListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
//   b
//   a

emitter.prependListener(eventName, listener)

Добавлено в: v6.0.0
  • eventName <string> | <symbol> Имя события.
  • listener <Function> Функция обратного вызова
  • Возвращает: <EventEmitter>

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

server.prependListener('connection', (stream) => {
  console.log('someone connected!');
}); copy

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

emitter.prependOnceListener(eventName, listener)

Добавлено в: v6.0.0
  • eventName <string> | <symbol> Имя события.
  • listener <Function> Функция обратного вызова
  • Возвращает: <EventEmitter>

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

server.prependOnceListener('connection', (stream) => {
  console.log('Ah, we have our first user!');
}); copy

Возвращает ссылку на 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('someone connected!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback); copy

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

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

Модули JavaScript
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();

const callbackA = () => {
  console.log('A');
  myEmitter.removeListener('event', callbackB);
};

const callbackB = () => {
  console.log('B');
};

myEmitter.on('event', callbackA);

myEmitter.on('event', callbackB);

// callbackA removes listener callbackB but it will still be called.
// Internal listener array at time of emit [callbackA, callbackB]
myEmitter.emit('event');
// Prints:
//   A
//   B

// callbackB is now removed.
// Internal listener array [callbackA]
myEmitter.emit('event');
// Prints:
//   A
CommonJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();

const callbackA = () => {
  console.log('A');
  myEmitter.removeListener('event', callbackB);
};

const callbackB = () => {
  console.log('B');
};

myEmitter.on('event', callbackA);

myEmitter.on('event', callbackB);

// callbackA removes listener callbackB but it will still be called.
// Internal listener array at time of emit [callbackA, callbackB]
myEmitter.emit('event');
// Prints:
//   A
//   B

// callbackB is now removed.
// Internal listener array [callbackA]
myEmitter.emit('event');
// Prints:
//   A

Поскольку обработчики управляются с помощью внутреннего массива, вызов этого метода изменит индексы всех обработчиков, зарегистрированных после удаляемого. Это не повлияет на порядок вызова обработчиков, однако потребуется заново создать все копии массива обработчиков, возвращаемые методом emitter.listeners().

Если одна функция добавлена как обработчик одного события несколько раз (как в примере ниже), метод removeListener() удалит экземпляр, добавленный последним. В примере удаляется обработчик once('ping'):

Модули JavaScript
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');
CommonJS
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()).

Модули JavaScript
import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.once('log', () => console.log('log once'));

// Returns a new Array with a function `onceWrapper` which has a property
// `listener` which contains the original listener bound above
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];

// Logs "log once" to the console and does not unbind the `once` event
logFnWrapper.listener();

// Logs "log once" to the console and removes the listener
logFnWrapper();

emitter.on('log', () => console.log('log persistently'));
// Will return a new Array with a single function bound by `.on()` above
const newListeners = emitter.rawListeners('log');

// Logs "log persistently" twice
newListeners[0]();
emitter.emit('log');
CommonJS
const EventEmitter = require('node:events');
const emitter = new EventEmitter();
emitter.once('log', () => console.log('log once'));

// Returns a new Array with a function `onceWrapper` which has a property
// `listener` which contains the original listener bound above
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];

// Logs "log once" to the console and does not unbind the `once` event
logFnWrapper.listener();

// Logs "log once" to the console and removes the listener
logFnWrapper();

emitter.on('log', () => console.log('log persistently'));
// Will return a new Array with a single function bound by `.on()` above
const newListeners = emitter.rawListeners('log');

// Logs "log persistently" twice
newListeners[0]();
emitter.emit('log');

emitter[Symbol.for('nodejs.rejection')](err, eventName[, ...args])

История
Версия Изменения
v17.4.0, v16.14.0

Больше не является экспериментальным.

v13.4.0, v12.16.0

Добавлено в: v13.4.0, v12.16.0

  • err <Error>
  • eventName <string> | <symbol>
  • ...args <any>

Метод Symbol.for('nodejs.rejection') вызывается в случае отклонения промиса при генерации события, если для эмиттера включён параметр captureRejections. Вместо Symbol.for('nodejs.rejection') можно использовать events.captureRejectionSymbol.

Модули JavaScript
import { EventEmitter, captureRejectionSymbol } from 'node:events';

class MyClass extends EventEmitter {
  constructor() {
    super({ captureRejections: true });
  }

  [captureRejectionSymbol](err, event, ...args) {
    console.log('rejection happened for', event, 'with', err, ...args);
    this.destroy(err);
  }

  destroy(err) {
    // Tear the resource down here.
  }
}
CommonJS
const { EventEmitter, captureRejectionSymbol } = require('node:events');

class MyClass extends EventEmitter {
  constructor() {
    super({ captureRejections: true });
  }

  [captureRejectionSymbol](err, event, ...args) {
    console.log('rejection happened for', event, 'with', err, ...args);
    this.destroy(err);
  }

  destroy(err) {
    // Tear the resource down here.
  }
}

events.defaultMaxListeners

Добавлено в: 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. Хотя для отдельных экземпляров AbortSignal по-прежнему можно установить лимит предупреждений с помощью emitter.setMaxListeners(n), по умолчанию экземпляры AbortSignal не выводят предупреждения.

Модули JavaScript
import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.setMaxListeners(emitter.getMaxListeners() + 1);
emitter.once('event', () => {
  // do stuff
  emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0));
});
CommonJS
const EventEmitter = require('node:events');
const emitter = new EventEmitter();
emitter.setMaxListeners(emitter.getMaxListeners() + 1);
emitter.once('event', () => {
  // do stuff
  emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0));
});

Флаг командной строки --trace-warnings можно использовать для отображения трассировки стека таких предупреждений.

Выведенное предупреждение можно проверить с помощью process.on('warning'); оно будет содержать дополнительные свойства emitter, type и count, указывающие соответственно на экземпляр эмиттера событий, имя события и количество подключенных обработчиков. Свойству name присваивается значение 'MaxListenersExceededWarning'.

events.errorMonitor

Добавлено в: v13.6.0, v12.17.0

Этот символ следует использовать для установки обработчика, предназначенного только для мониторинга событий 'error'. Обработчики, установленные с помощью этого символа, вызываются до вызова обычных обработчиков 'error'.

Установка обработчика с помощью этого символа не меняет поведение после возникновения события 'error'. Поэтому процесс все равно завершится с аварийным завершением, если обычный обработчик 'error' не установлен.

events.getEventListeners(emitterOrTarget, eventName)

Добавлено в: v15.2.0, v14.17.0
  • emitterOrTarget <EventEmitter> | <EventTarget>
  • eventName <string> | <symbol>
  • Возвращает: <Function[]>

Возвращает копию массива обработчиков события с именем eventName.

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

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

Модули JavaScript
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] ]
}
CommonJS
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>

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

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

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

Модули JavaScript
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
}
CommonJS
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>
  • name <string> | <symbol>
  • options <Object>
    • signal <AbortSignal> Можно использовать для отмены ожидания события.
  • Возвращает: <Promise>

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

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

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

Модули JavaScript
import { EventEmitter, once } from 'node:events';

const ee = new EventEmitter();

once(ee, 'error')
  .then(([err]) => console.log('ok', err.message))
  .catch((err) => console.error('error', err.message));

ee.emit('error', new Error('boom'));

// Prints: ok boom
CommonJS
const { EventEmitter, once } = require('node:events');

const ee = new EventEmitter();

once(ee, 'error')
  .then(([err]) => console.log('ok', err.message))
  .catch((err) => console.error('error', err.message));

ee.emit('error', new Error('boom'));

// Prints: ok boom

Для отмены ожидания события можно использовать <AbortSignal>:

Модули JavaScript
import { EventEmitter, once } from 'node:events';

const ee = new EventEmitter();
const ac = new AbortController();

async function foo(emitter, event, signal) {
  try {
    await once(emitter, event, { signal });
    console.log('event emitted!');
  } catch (error) {
    if (error.name === 'AbortError') {
      console.error('Waiting for the event was canceled!');
    } else {
      console.error('There was an error', error.message);
    }
  }
}

foo(ee, 'foo', ac.signal);
ac.abort(); // Prints: Waiting for the event was canceled!
CommonJS
const { EventEmitter, once } = require('node:events');

const ee = new EventEmitter();
const ac = new AbortController();

async function foo(emitter, event, signal) {
  try {
    await once(emitter, event, { signal });
    console.log('event emitted!');
  } catch (error) {
    if (error.name === 'AbortError') {
      console.error('Waiting for the event was canceled!');
    } else {
      console.error('There was an error', error.message);
    }
  }
}

foo(ee, 'foo', ac.signal);
ac.abort(); // Prints: Waiting for the event was canceled!

Ожидание нескольких событий, сгенерированных в process.nextTick()

При использовании функции events.once() для ожидания нескольких событий, сгенерированных в одном пакете операций process.nextTick(), или в случаях, когда несколько событий генерируются синхронно, следует учитывать один особый случай. В частности, поскольку очередь process.nextTick() обрабатывается до очереди микрозадач Promise, а EventEmitter синхронно генерирует все события, events.once() может пропустить событие.

Модули JavaScript
import { EventEmitter, once } from 'node:events';
import process from 'node:process';

const myEE = new EventEmitter();

async function foo() {
  await once(myEE, 'bar');
  console.log('bar');

  // This Promise will never resolve because the 'foo' event will
  // have already been emitted before the Promise is created.
  await once(myEE, 'foo');
  console.log('foo');
}

process.nextTick(() => {
  myEE.emit('bar');
  myEE.emit('foo');
});

foo().then(() => console.log('done'));
CommonJS
const { EventEmitter, once } = require('node:events');

const myEE = new EventEmitter();

async function foo() {
  await once(myEE, 'bar');
  console.log('bar');

  // This Promise will never resolve because the 'foo' event will
  // have already been emitted before the Promise is created.
  await once(myEE, 'foo');
  console.log('foo');
}

process.nextTick(() => {
  myEE.emit('bar');
  myEE.emit('foo');
});

foo().then(() => console.log('done'));

Чтобы получить оба события, создайте все промисы до ожидания любого из них; после этого можно использовать Promise.all(), Promise.race() или Promise.allSettled():

Модули JavaScript
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'));
CommonJS
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> Symbol.for('nodejs.rejection')

См. инструкции по созданию пользовательского обработчика отклонений.

events.listenerCount(emitterOrTarget, eventName)

История
Версия Изменения
v24.14.0

Теперь принимает аргументы EventTarget.

v24.14.0

Отмена пометки об устаревании.

v3.2.0

Пометка об устаревании только в документации.

v0.9.12

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

  • emitterOrTarget <EventEmitter> | <EventTarget>
  • eventName <string> | <symbol>
  • Возвращает: <integer>

Возвращает количество зарегистрированных обработчиков события с именем eventName.

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

Для EventTargets это единственный способ получить количество обработчиков. Это может быть полезно для отладки и диагностики.

Модули JavaScript
import { EventEmitter, listenerCount } from 'node:events';

{
  const ee = new EventEmitter();
  ee.on('event', () => {});
  ee.on('event', () => {});
  console.log(listenerCount(ee, 'event')); // 2
}
{
  const et = new EventTarget();
  et.addEventListener('event', () => {});
  et.addEventListener('event', () => {});
  console.log(listenerCount(et, 'event')); // 2
}
CommonJS
const { EventEmitter, listenerCount } = require('node:events');

{
  const ee = new EventEmitter();
  ee.on('event', () => {});
  ee.on('event', () => {});
  console.log(listenerCount(ee, 'event')); // 2
}
{
  const et = new EventTarget();
  et.addEventListener('event', () => {});
  et.addEventListener('event', () => {});
  console.log(listenerCount(et, '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
Модули JavaScript
import { on, EventEmitter } from 'node:events';
import process from 'node:process';

const ee = new EventEmitter();

// Emit later on
process.nextTick(() => {
  ee.emit('foo', 'bar');
  ee.emit('foo', 42);
});

for await (const event of on(ee, 'foo')) {
  // The execution of this inner block is synchronous and it
  // processes one event at a time (even with await). Do not use
  // if concurrent execution is required.
  console.log(event); // prints ['bar'] [42]
}
// Unreachable here
CommonJS
const { on, EventEmitter } = require('node:events');

(async () => {
  const ee = new EventEmitter();

  // Emit later on
  process.nextTick(() => {
    ee.emit('foo', 'bar');
    ee.emit('foo', 42);
  });

  for await (const event of on(ee, 'foo')) {
    // The execution of this inner block is synchronous and it
    // processes one event at a time (even with await). Do not use
    // if concurrent execution is required.
    console.log(event); // prints ['bar'] [42]
  }
  // Unreachable here
})();

Возвращает AsyncIterator, который перебирает события eventName. Если EventEmitter генерирует 'error', возникает ошибка. При выходе из цикла все обработчики удаляются. value, возвращаемое на каждой итерации, представляет собой массив аргументов сгенерированного события.

Для отмены ожидания событий можно использовать <AbortSignal>:

Модули JavaScript
import { on, EventEmitter } from 'node:events';
import process from 'node:process';

const ac = new AbortController();

(async () => {
  const ee = new EventEmitter();

  // Emit later on
  process.nextTick(() => {
    ee.emit('foo', 'bar');
    ee.emit('foo', 42);
  });

  for await (const event of on(ee, 'foo', { signal: ac.signal })) {
    // The execution of this inner block is synchronous and it
    // processes one event at a time (even with await). Do not use
    // if concurrent execution is required.
    console.log(event); // prints ['bar'] [42]
  }
  // Unreachable here
})();

process.nextTick(() => ac.abort());
CommonJS
const { on, EventEmitter } = require('node:events');

const ac = new AbortController();

(async () => {
  const ee = new EventEmitter();

  // Emit later on
  process.nextTick(() => {
    ee.emit('foo', 'bar');
    ee.emit('foo', 42);
  });

  for await (const event of on(ee, 'foo', { signal: ac.signal })) {
    // The execution of this inner block is synchronous and it
    // processes one event at a time (even with await). Do not use
    // if concurrent execution is required.
    console.log(event); // prints ['bar'] [42]
  }
  // Unreachable here
})();

process.nextTick(() => ac.abort());

events.setMaxListeners(n[, ...eventTargets])

Добавлено в: v15.4.0
  • n <number> Неотрицательное число. Максимальное количество обработчиков на событие EventTarget.
  • ...eventsTargets <EventTarget[]> | <EventEmitter[]> Ноль или более экземпляров <EventTarget> или <EventEmitter>. Если экземпляры не указаны, n устанавливается как максимальное значение по умолчанию для всех вновь созданных объектов <EventTarget> и <EventEmitter>.
Модули JavaScript
import { setMaxListeners, EventEmitter } from 'node:events';

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

setMaxListeners(5, target, emitter);
CommonJS
const {
  setMaxListeners,
  EventEmitter,
} = require('node:events');

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

setMaxListeners(5, target, emitter);

events.addAbortListener(signal, listener)

История
Версия Изменения
v24.0.0

Статус стабильности этой функции изменен с экспериментального на стабильный.

v20.5.0, v18.18.0

Добавлено в: v20.5.0, v18.18.0

  • signal <AbortSignal>
  • listener <Function> | <EventListener>
  • Возвращает: <Disposable> Объект Disposable, удаляющий обработчик abort.

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

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

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

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

CommonJS
const { addAbortListener } = require('node:events');

function example(signal) {
  let disposable;
  try {
    signal.addEventListener('abort', (e) => e.stopImmediatePropagation());
    disposable = addAbortListener(signal, (e) => {
      // Do something when signal is aborted.
    });
  } finally {
    disposable?.[Symbol.dispose]();
  }
}
Модули JavaScript
import { addAbortListener } from 'node:events';

function example(signal) {
  let disposable;
  try {
    signal.addEventListener('abort', (e) => e.stopImmediatePropagation());
    disposable = addAbortListener(signal, (e) => {
      // Do something when signal is aborted.
    });
  } finally {
    disposable?.[Symbol.dispose]();
  }
}

Класс: events.EventEmitterAsyncResource extends EventEmitter

Добавлено в: v17.4.0, v16.14.0

Интегрирует EventEmitter с <AsyncResource> для EventEmitter, которым требуется ручное отслеживание асинхронных операций. В частности, все события, сгенерированные экземплярами events.EventEmitterAsyncResource, выполняются в их асинхронном контексте.

Модули JavaScript
import { EventEmitterAsyncResource, EventEmitter } from 'node:events';
import { notStrictEqual, strictEqual } from 'node:assert';
import { executionAsyncId, triggerAsyncId } from 'node:async_hooks';

// Async tracking tooling will identify this as 'Q'.
const ee1 = new EventEmitterAsyncResource({ name: 'Q' });

// 'foo' listeners will run in the EventEmitters async context.
ee1.on('foo', () => {
  strictEqual(executionAsyncId(), ee1.asyncId);
  strictEqual(triggerAsyncId(), ee1.triggerAsyncId);
});

const ee2 = new EventEmitter();

// 'foo' listeners on ordinary EventEmitters that do not track async
// context, however, run in the same async context as the emit().
ee2.on('foo', () => {
  notStrictEqual(executionAsyncId(), ee2.asyncId);
  notStrictEqual(triggerAsyncId(), ee2.triggerAsyncId);
});

Promise.resolve().then(() => {
  ee1.emit('foo');
  ee2.emit('foo');
});
CommonJS
const { EventEmitterAsyncResource, EventEmitter } = require('node:events');
const { notStrictEqual, strictEqual } = require('node:assert');
const { executionAsyncId, triggerAsyncId } = require('node:async_hooks');

// Async tracking tooling will identify this as 'Q'.
const ee1 = new EventEmitterAsyncResource({ name: 'Q' });

// 'foo' listeners will run in the EventEmitters async context.
ee1.on('foo', () => {
  strictEqual(executionAsyncId(), ee1.asyncId);
  strictEqual(triggerAsyncId(), ee1.triggerAsyncId);
});

const ee2 = new EventEmitter();

// 'foo' listeners on ordinary EventEmitters that do not track async
// context, however, run in the same async context as the emit().
ee2.on('foo', () => {
  notStrictEqual(executionAsyncId(), ee2.asyncId);
  notStrictEqual(triggerAsyncId(), ee2.triggerAsyncId);
});

Promise.resolve().then(() => {
  ee1.emit('foo');
  ee2.emit('foo');
});

Класс EventEmitterAsyncResource имеет те же методы и принимает те же параметры, что и сами EventEmitter и AsyncResource.

new events.EventEmitterAsyncResource([options])

  • options <Object>
    • captureRejections <boolean> Включает автоматический перехват отклонений промисов. По умолчанию: false.
    • name <string> Тип асинхронного события. По умолчанию: new.target.name.
    • triggerAsyncId <number> Идентификатор контекста выполнения, в котором создано это асинхронное событие. По умолчанию: executionAsyncId().
    • requireManualDestroy <boolean> Если установлено значение true, вызов emitDestroy при сборке объекта мусора отключается. Обычно это не требуется (даже если emitDestroy вызван вручную), за исключением случая, когда получено свойство asyncId ресурса и с ним вызван emitDestroy конфиденциального API. Если установлено значение false, вызов emitDestroy при сборке мусора произойдет только при наличии хотя бы одного активного перехватчика destroy. По умолчанию: false.

eventemitterasyncresource.asyncId

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

eventemitterasyncresource.asyncResource

  • Тип: <AsyncResource> Базовый объект <AsyncResource>.

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

eventemitterasyncresource.emitDestroy()

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

eventemitterasyncresource.triggerAsyncId

  • Тип: <number> Тот же triggerAsyncId, который передается конструктору AsyncResource.

API EventTarget и Event

История
Версия Изменения
v16.0.0

изменена обработка ошибок EventTarget.

v15.4.0

Больше не является экспериментальным.

v15.0.0

Классы EventTarget и Event теперь доступны как глобальные объекты.

v14.5.0

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

Объекты EventTarget и Event представляют собой специфичную для Node.js реализацию веб-API EventTarget, предоставляемую некоторыми основными API Node.js.

const target = new EventTarget();

target.addEventListener('foo', (event) => {
  console.log('foo event happened!');
}); copy

Node.js EventTarget и DOM EventTarget

Между EventTarget Node.js и веб-API EventTarget есть два ключевых различия:

  1. В отличие от DOM, экземпляры EventTarget могут быть иерархическими, однако в Node.js понятия иерархии и распространения событий отсутствуют. То есть событие, отправленное объекту EventTarget, не распространяется по иерархии вложенных целевых объектов, каждый из которых может иметь собственный набор обработчиков этого события.
  2. В EventTarget Node.js, если слушатель события является асинхронной функцией или возвращает Promise, а возвращённый Promise отклоняется, отклонение автоматически перехватывается и обрабатывается так же, как исключение, синхронно выброшенное слушателем (подробности см. в разделе Обработка ошибок EventTarget).

NodeEventTarget и EventEmitter

Объект NodeEventTarget реализует изменённое подмножество API EventEmitter, позволяющее в некоторых ситуациях близко имитировать EventEmitter. NodeEventTarget не является экземпляром EventEmitter и в большинстве случаев не может использоваться вместо EventEmitter.

  1. В отличие от EventEmitter, любой listener можно зарегистрировать не более одного раза для каждого события type. Повторные попытки зарегистрировать listener игнорируются.
  2. NodeEventTarget не имитирует весь API EventEmitter. В частности, API prependListener(), prependOnceListener(), rawListeners() и errorMonitor не имитируются. События 'newListener' и 'removeListener' также не генерируются.
  3. NodeEventTarget не реализует специальное поведение по умолчанию для событий с типом 'error'.
  4. NodeEventTarget поддерживает объекты EventListener, а также функции в качестве обработчиков для всех типов событий.

Слушатель события

Слушатели события, зарегистрированные для события type, могут быть как функциями JavaScript, так и объектами со свойством handleEvent, значением которого является функция.

В обоих случаях вызывается функция-обработчик, которой передаётся аргумент event, переданный функции eventTarget.dispatchEvent().

В качестве слушателей событий можно использовать асинхронные функции. Если асинхронный обработчик отклоняет Promise, отклонение перехватывается и обрабатывается, как описано в разделе Обработка ошибок EventTarget.

Исключение, выброшенное одной функцией-обработчиком, не препятствует вызову остальных обработчиков.

Возвращаемое значение функции-обработчика игнорируется.

Обработчики всегда вызываются в порядке их добавления.

Функции-обработчики могут изменять объект event.

function handler1(event) {
  console.log(event.type);  // Prints 'foo'
  event.a = 1;
}

async function handler2(event) {
  console.log(event.type);  // Prints 'foo'
  console.log(event.a);  // Prints 1
}

const handler3 = {
  handleEvent(event) {
    console.log(event.type);  // Prints 'foo'
  },
};

const handler4 = {
  async handleEvent(event) {
    console.log(event.type);  // Prints 'foo'
  },
};

const target = new EventTarget();

target.addEventListener('foo', handler1);
target.addEventListener('foo', handler2);
target.addEventListener('foo', handler3);
target.addEventListener('foo', handler4, { once: true }); copy

Обработка ошибок 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 представляет собой адаптацию веб-API Event. Экземпляры создаются Node.js.

event.bubbles
Добавлено в: v14.5.0
  • Тип: <boolean> Всегда возвращает false.

В Node.js это свойство не используется и предоставлено исключительно для полноты API.

event.cancelBubble
Добавлено в: v14.5.0
Стабильность: 3 — Устаревшее: вместо него используйте event.stopPropagation().
  • Тип: <boolean>

Синоним event.stopPropagation(), если установлено значение true. В Node.js это свойство не используется и предоставлено исключительно для полноты API.

event.cancelable
Добавлено в: v14.5.0
  • Тип: <boolean> Возвращает true, если событие было создано с параметром cancelable.
event.composed
Добавлено в: v14.5.0
  • Тип: <boolean> Всегда возвращает false.

В Node.js это свойство не используется и предоставлено исключительно для полноты API.

event.composedPath()
Добавлено в: v14.5.0

Возвращает массив, содержащий текущий EventTarget в качестве единственного элемента, или пустой массив, если событие не отправляется. В Node.js это свойство не используется и предоставлено исключительно для полноты API.

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 это свойство не используется и предоставлено исключительно для полноты API.

event.initEvent(type[, bubbles[, cancelable]])
Добавлено в: v19.5.0
Стабильность: 3 — Устаревшее: согласно спецификации WHATWG, этот метод устарел, и его не следует использовать.
  • type <string>
  • bubbles <boolean>
  • cancelable <boolean>

Избыточен при наличии конструкторов событий и не позволяет задать composed. В Node.js этот метод не используется и предоставлен исключительно для полноты API.

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 — Устаревшее: вместо него используйте event.defaultPrevented.
  • Тип: <boolean> True, если событие не было отменено.

Значение event.returnValue всегда противоположно значению event.defaultPrevented. В Node.js это свойство не используется и предоставлено исключительно для полноты API.

event.srcElement
Добавлено в: v14.5.0
Стабильность: 3 — Устаревшее: вместо него используйте event.target.
  • Тип: <EventTarget> Объект EventTarget, отправляющий событие.

Синоним event.target.

event.stopImmediatePropagation()
Добавлено в: v14.5.0

Останавливает вызов слушателей событий после завершения работы текущего слушателя.

event.stopPropagation()
Добавлено в: v14.5.0

В Node.js это свойство не используется и предоставлено исключительно для полноты API.

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 });  // first
target.addEventListener('foo', handler, { capture: false }); // second

// Removes the second instance of handler
target.removeEventListener('foo', handler);

// Removes the first instance of handler
target.removeEventListener('foo', handler, { capture: true }); copy
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.

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

  • Наследует: <Event>

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

event.detail
История
Версия Изменения
v22.1.0, v20.13.0

CustomEvent теперь имеет стабильный статус.

v18.7.0, v16.17.0

Добавлено в: v18.7.0, v16.17.0

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

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

Класс: NodeEventTarget

Добавлено в: v14.5.0
  • Наследует: <EventTarget>

NodeEventTarget — это специфичное для 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
  • type <string>

  • Возвращает: <number>

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

© Joyent, Inc. and other Node contributors
Licensed under the MIT License.
Node.js is a trademark of Joyent, Inc. and is used with its permission.
We are not endorsed by or affiliated with Joyent.
https://nodejs.org/dist/latest-v24.x/docs/api/events.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API