Spec-Zone.ru › Node.js 16 LTS

События

Устойчивость: 2 - Стабильно

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

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

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

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

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

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

const EventEmitter = require('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, к которому прикреплен слушатель.

const myEmitter = new MyEmitter();
myEmitter.on('event', function(a, b) {
  console.log(a, b, this, this === myEmitter);
  // Prints:
  //   a b MyEmitter {
  //     domain: null,
  //     _events: { event: [Function] },
  //     _eventsCount: 1,
  //     _maxListeners: undefined } true
});
myEmitter.emit('event', 'a', 'b');

Можно использовать функции стрелок ES6 в качестве слушателей, однако в этом случае ключевое слово this больше не будет ссылаться на экземпляр 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():

const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
  setImmediate(() => {
    console.log('this happens asynchronously');
  });
});
myEmitter.emit('event', 'a', 'b');

Обработка событий только один раз

Когда слушатель регистрируется с помощью метода eventEmitter.on(), этот слушатель вызывается каждый раз, когда излучается именованное событие.

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

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 завершается.

const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// Throws and crashes Node.js

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

В качестве лучшей практики, для событий 'error' всегда следует добавлять слушателей.

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.

const { EventEmitter, errorMonitor } = require('events');

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

Перехват отклонений обещаний

Устойчивость: 1 - captureRejections экспериментально.

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

const ee = new EventEmitter();
ee.on('something', async (value) => {
  throw new Error('kaboom');
});

Опция captureRejections в конструкторе EventEmitter или глобальная настройка изменяют это поведение, устанавливая обработчик .then(undefined, handler) для Promise. Этот обработчик асинхронно перенаправляет исключение в метод Symbol.for('nodejs.rejection'), если он существует, или к обработчику события 'error', если его нет.

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.

const events = require('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 определён и экспортирован модулем events.

const EventEmitter = require('events');

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

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

  • captureRejections <boolean> Включает автоматическое перехват отмены обещаний. По умолчанию: false.

Событие: 'newListener'

Добавлен в: v0.1.26
  • eventName <string> | <symbol> Имя события, на которое подписываются
  • listener <Функция> Функция-обработчик события

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

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

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

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 <Функция> Функция-обработчик события

Событие 'removeListener' генерируется после удаления listener.

emitter.addListener(eventName, listener)

Добавлен в: v0.1.26
  • eventName <string> | <symbol>
  • listener <Функция>

Псевдоним для emitter.on(eventName, listener).

emitter.emit(eventName[, ...args])

Добавлен в: v0.1.26
  • eventName <string> | <symbol>
  • ...args <любой тип>
  • Возвращает: <boolean>

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

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

const EventEmitter = require('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
  • Возвращает: <Массив>

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

const EventEmitter = require('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
  • Возвращает: <целое число>

Возвращает текущее максимальное значение слушателей для EventEmitter, которое устанавливается с помощью emitter.setMaxListeners(n) или по умолчанию равно events.defaultMaxListeners.

emitter.listenerCount(eventName)

Добавлен в: v3.2.0
  • eventName <string> | <symbol> Имя события, на которое подписываются
  • Возвращает: <целое число>

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

emitter.listeners(eventName)

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

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

v0.1.26

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

  • eventName <string> | <symbol>
  • Возвращает: <Функция[]>

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

server.on('connection', (stream) => {
  console.log('someone connected!');
});
console.log(util.inspect(server.listeners('connection')));
// Prints: [ [Function] ]

emitter.off(eventName, listener)

Добавлен в: v10.0.0
  • eventName <string> | <symbol>
  • listener <Функция>
  • Возвращает: <EventEmitter>

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

emitter.on(eventName, listener)

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

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

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

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

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

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 <Функция> Функция обратного вызова
  • Возвращает: <EventEmitter>

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

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

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

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

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 <Функция> Функция обратного вызова
  • Возвращает: <EventEmitter>

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

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

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

emitter.prependOnceListener(eventName, listener)

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

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

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

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

emitter.removeAllListeners([eventName])

Добавлен в: v0.1.26
  • eventName <строка> | <символ>
  • Возвращает: <EventEmitter>

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

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

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

emitter.removeListener(eventName, listener)

Добавлен в: v0.1.26
  • eventName <строка> | <символ>
  • listener <Функция>
  • Возвращает: <EventEmitter>

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

const callback = (stream) => {
  console.log('someone connected!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback);

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

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

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

const ee = new EventEmitter();

function pong() {
  console.log('pong');
}

ee.on('ping', pong);
ee.once('ping', pong);
ee.removeListener('ping', pong);

ee.emit('ping');
ee.emit('ping');

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

emitter.setMaxListeners(n)

Добавлен в: v0.3.5
  • n <целое число>
  • Возвращает: <EventEmitter>

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

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

emitter.rawListeners(eventName)

Добавлен в: v9.4.0
  • eventName <строка> | <символ>
  • Возвращает: <Функция[]>

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

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

Добавлен в: v13.4.0, v12.16.0
Устойчивость: 1 - captureRejections является экспериментальным.
  • err Ошибка
  • eventName <строка> | <символ>
  • ...args <любое>

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

const { EventEmitter, captureRejectionSymbol } = require('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() для временного предотвращения этого предупреждения:

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
  • emitterOrTarget <EventEmitter> | <EventTarget>
  • eventName <строка> | <символ>
  • Возвращает: <Функция[]>

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

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

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

const { getEventListeners, EventEmitter } = require('events');

{
  const ee = new EventEmitter();
  const listener = () => console.log('Events are fun');
  ee.on('foo', listener);
  getEventListeners(ee, 'foo'); // [listener]
}
{
  const et = new EventTarget();
  const listener = () => console.log('Events are fun');
  et.addEventListener('foo', listener);
  getEventListeners(et, 'foo'); // [listener]
}

events.once(emitter, name[, options])

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

Теперь поддерживается опция signal.

v11.13.0, v10.16.0

Добавлена в: v11.13.0, v10.16.0

  • emitter <EventEmitter>
  • name <строка>
  • options <Объект>
    • signal <AbortSignal> Можно использовать для отмены ожидания события.
  • Возвращает: <Promise>

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

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

const { once, EventEmitter } = require('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.log('error happened', err);
  }
}

run();

Специальная обработка события 'error' используется только тогда, когда events.once() используется для ожидания другого события. Если events.once() используется для ожидания события 'error'', то оно обрабатывается как любое другое событие без специальной обработки:

const { EventEmitter, once } = require('events');

const ee = new EventEmitter();

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

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

// Prints: ok boom

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

const { EventEmitter, once } = require('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(); // Abort waiting for the event
ee.emit('foo'); // Prints: Waiting for the event was canceled!

Ожидание нескольких событий, излучаемых на process.nextTick()

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

const { EventEmitter, once } = require('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():

const { EventEmitter, once } = require('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

Добавлена в: v13.4.0, v12.16.0
Стабильность: 1 - captureRejections экспериментальная.

Значение: <логическое>

Изменить значение опции captureRejections по умолчанию для всех новых объектов EventEmitter.

events.captureRejectionSymbol

Добавлена в: v13.4.0, v12.16.0
Стабильность: 1 - captureRejections экспериментальная.

Значение: Symbol.for('nodejs.rejection')

Посмотрите, как написать пользовательскую обработку обработчик отклонения.

events.listenerCount(emitter, eventName)

Добавлена в: v0.9.12Устарела с: v3.2.0
Стабильность: 0 - Устарело: Используйте emitter.listenerCount() вместо этого.
  • emitter <EventEmitter> Эмиттер для запроса
  • eventName <строка> | <символ> Название события

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

const { EventEmitter, listenerCount } = require('events');
const myEmitter = new EventEmitter();
myEmitter.on('event', () => {});
myEmitter.on('event', () => {});
console.log(listenerCount(myEmitter, 'event'));
// Prints: 2

events.on(emitter, eventName[, options])

Добавлена в: v13.6.0, v12.16.0
  • emitter <EventEmitter>
  • eventName <строка> | <символ> Имя события, на которое подписываются
  • options <Объект>
    • signal <AbortSignal> Можно использовать для отмены ожидания событий.
  • Возвращает: <AsyncIterator>, которая итерирует eventName события, излучаемые emitter
const { on, EventEmitter } = require('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> для отмены ожидания событий:

const { on, EventEmitter } = require('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 <число> Неотрицательное число. Максимальное количество обработчиков на событие EventTarget.
  • ...eventsTargets <EventTarget[]> | <EventEmitter[]> Ноль или более экземпляров <EventTarget> или <EventEmitter>. Если ни один не указан, n устанавливается как значение по умолчанию для всех вновь созданных объектов <EventTarget> и <EventEmitter>.
const {
  setMaxListeners,
  EventEmitter
} = require('events');

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

setMaxListeners(5, target, emitter);

EventTarget и Event API

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

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

v15.4.0

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

v15.0.0

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

v14.5.0

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

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

const target = new EventTarget();

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

Node.js EventTarget по сравнению с DOM EventTarget

Существует два ключевых различия между Node.js EventTarget и EventTarget Web API:

  1. В то время как экземпляры DOM EventTarget могут быть иерархическими, в Node.js нет понятия иерархии и распространения событий. То есть событие, отправленное в EventTarget, не распространяется через иерархию вложенных целевых объектов, каждый из которых может иметь свой собственный набор обработчиков для события.
  2. В Node.js EventTarget, если обработчик события — это асинхронная функция или функция, возвращающая 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(), setMaxListeners(), getMaxListeners() и errorMonitor не эмулируются. События 'newListener' и 'removeListener' также не будут генерироваться.
  3. Объект NodeEventTarget не реализует никаких специальных стандартных действий для событий с типом 'error'.
  4. Объект NodeEventTarget поддерживает объекты EventListener и функции в качестве обработчиков для всех типов событий.

Обработчик события

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

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

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

Ошибка, выброшенная одной функцией-обработчиком, не предотвращает вызов других зарегистрированных обработчиков.

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

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

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

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

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

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

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

const target = new EventTarget();

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

EventTarget обработка ошибок

Когда зарегистрированный обработчик события выбрасывает ошибку (или возвращает Promise, который отклоняется), по умолчанию ошибка обрабатывается как непредвиденное исключение в process.nextTick(). Это означает, что непредвиденные исключения в EventTarget по умолчанию приведут к завершению процесса Node.js.

Выброс ошибки внутри обработчика событий не останавливает вызов других зарегистрированных обработчиков.

Объект EventTarget не реализует никакой специальной обработки по умолчанию для событий типа '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

Псевдоним для event.stopPropagation(). Это не используется в Node.js и предоставляется исключительно для полноты.

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

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

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

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

event.currentTarget
Добавлена в: v14.5.0
  • Тип: <EventTarget> EventTarget отправляющий событие.

Псевдоним для event.target.

event.defaultPrevented
Добавлена в: v14.5.0
  • Тип: <boolean>

Истинно, если cancelable равно true и event.preventDefault() был вызван.

event.eventPhase
Добавлена в: v14.5.0
  • Тип: <number> Возвращает 0, когда событие не обрабатывается, и 2, когда оно обрабатывается.

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

event.isTrusted
Добавлена в: v14.5.0
  • Тип: <boolean>

Событие <AbortSignal> "abort" генерируется со значением isTrusted, установленным в true. В остальных случаях значение равно false.

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

Устанавливает свойство defaultPrevented в значение true, если cancelable равно true.

event.returnValue
Добавлена в: v14.5.0
  • Тип: <boolean> Истина, если событие не было отменено.

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

event.srcElement
Добавлена в: v14.5.0
  • Тип: <EventTarget> EventTarget отправляющий событие.

Псевдоним для event.target.

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

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

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

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

event.target
Добавлена в: v14.5.0
  • Тип: <EventTarget> EventTarget отправляющий событие.
event.timeStamp
Добавлена в: v14.5.0
  • Тип: <number>

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

event.type
Добавлена в: v14.5.0
  • Тип: <string>

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

Класс: EventTarget

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

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

v14.5.0

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

eventTarget.addEventListener(type, listener[, options])
Добавлена в: 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.

Добавляет новый обработчик для события 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 });
eventTarget.dispatchEvent(event)
Добавлена в: v14.5.0
  • event <Event>
  • Возвращает: <boolean> true если значение атрибута cancelable события или метод preventDefault() не был вызван, в противном случае false.

Отправляет событие event в список обработчиков для event.type.

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

eventTarget.removeEventListener(type, listener)
Добавлена в: v14.5.0
  • type <string>
  • listener <Function> | <EventListener>
  • options <Object>
    • capture <boolean>

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

Класс: NodeEventTarget

Добавлена в: v14.5.0
  • Расширяет: <EventTarget>

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

nodeEventTarget.addListener(type, listener[, options])
Добавлена в: v14.5.0
  • type <string>

  • listener <Function> | <EventListener>

  • options <Object>

    • once <boolean>
  • Возвращает: <EventTarget> this

Расширение, специфичное для Node.js, класса EventTarget, которое эмулирует эквивалентный API EventEmitter. Единственное отличие между addListener() и addEventListener() состоит в том, что addListener() вернёт ссылку на EventTarget.

nodeEventTarget.eventNames()
Добавлена в: v14.5.0
  • Возвращает: <string[]>

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

nodeEventTarget.listenerCount(type)
Добавлена в: v14.5.0
  • type <string>

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

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

nodeEventTarget.off(type, listener)
Добавлена в: v14.5.0
  • type <string>

  • listener <Function> | <EventListener>

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

Специфический для Node.js псевдоним для eventTarget.removeListener().

nodeEventTarget.on(type, listener[, options])
Добавлена в: v14.5.0
  • type <string>

  • listener <Function> | <EventListener>

  • options <Object>

    • once <boolean>
  • Возвращает: <EventTarget> this

Специфический для Node.js псевдоним для eventTarget.addListener().

nodeEventTarget.once(type, listener[, options])
Добавлена в: v14.5.0
  • type <string>

  • listener <Function> | <EventListener>

  • options <Object>

  • Возвращает: <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)
Добавлена в: v14.5.0
  • type <string>

  • listener <Function> | <EventListener>

  • Возвращает: <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-v16.x/docs/api/events.html

Spec-Zone.ru

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