Spec-Zone.ru › Node.js 18 LTS

События

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

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

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

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

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

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

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

Модули MJS

import { EventEmitter } from 'node:events';

class MyEmitter extends EventEmitter {}

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

Модули CJS

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

Модули MJS

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(kCapture)]: false
  //   } true
});
myEmitter.emit('event', 'a', 'b');

Модули CJS

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(kCapture)]: false
  //   } true
});
myEmitter.emit('event', 'a', 'b');

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

Модули MJS

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 {}
});
myEmitter.emit('event', 'a', 'b');

Модули CJS

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

Модули MJS

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

Модули CJS

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

Модули MJS

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

Модули CJS

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

Модули MJS

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

Модули CJS

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

Модули MJS

import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// Throws and crashes Node.js

Модули CJS

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

Модули MJS

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

Модули CJS

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.

Модули MJS

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

Модули CJS

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 с обработчиками событий проблематично, поскольку это может привести к необработанному отклонению в случае возникновения исключения:

Модули MJS

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

Модули CJS

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', если его нет.

Модули MJS

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;

Модули CJS

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.

Модули MJS

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

Модули CJS

const events = require('node:events');
events.captureRejections = true;
const ee1 = new events.EventEmitter();
ee1.on('something', async (value) => {
  throw new Error('kaboom');
});

ee1.on('error', console.log);

События 'error' , генерируемые поведением captureRejections , не имеют обработчика catch для предотвращения бесконечных циклов ошибок: рекомендуется не использовать функции async в качестве обработчиков событий 'error'.

Класс: EventEmitter

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

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

v0.1.26

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

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

Модули MJS

import { EventEmitter } from 'node:events';

Модули CJS

const EventEmitter = require('node:events');

Все экземпляры EventEmitter излучают событие 'newListener' при добавлении новых слушателей и 'removeListener' при удалении существующих слушателей.

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

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

Событие: 'newListener'

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

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

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

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

Модули MJS

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

Модули CJS

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

Модули MJS

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

Модули CJS

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
  • Возвращает: <Array>

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

Модули MJS

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

Модули CJS

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

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

emitter.listenerCount(eventName[, listener])

История
Версия Изменения
v18.16.0

Добавлен аргумент listener.

v3.2.0

Добавлен в: v3.2.0

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

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

Модули MJS

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

Модули CJS

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

Модули MJS

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

Модули CJS

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() в процессе. Последующие события ведут себя как ожидается.

Модули MJS

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

Модули CJS

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

Модули MJS

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

Модули CJS

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

Модули MJS

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

Модули CJS

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 Ошибка
  • eventName <string> | <symbol>
  • ...args <any>

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

Модули MJS

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

Модули CJS

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

Added in: 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() могут быть использованы для временного избегания этого предупреждения:

MJS модули

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

CJS модули

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

Added in: v13.6.0, v12.17.0

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

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

events.getEventListeners(emitterOrTarget, eventName)

Added in: v15.2.0, v14.17.0
  • emitterOrTarget <EventEmitter> | <EventTarget>
  • eventName <строка> | <символ>
  • Возвращает: <Массив функций>

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

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

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

MJS модули

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

CJS модули

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)

Added in: v18.17.0
  • emitterOrTarget <EventEmitter> | <EventTarget>
  • Возвращает: <число>

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

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

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

MJS модули

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
}

CJS модули

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 <строка>
  • options <объект>
    • signal <AbortSignal> Может быть использован для отмены ожидания события.
  • Возвращает: <Promise>

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

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

MJS модули

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

CJS модули

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

MJS модули

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

CJS модули

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

MJS модули

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(); // Abort waiting for the event
ee.emit('foo'); // Prints: Waiting for the event was canceled!

CJS модули

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

MJS модули

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

CJS модули

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

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

MJS модули

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

CJS модули

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

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

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

events.captureRejectionSymbol

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

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

v13.4.0, v12.16.0

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

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

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

events.listenerCount(emitter, eventName)

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

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

MJS модули

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

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

CJS модули

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

Модули MJS

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

Модули CJS

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

Модули MJS

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());

Модули CJS

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 <число> Неотрицательное число. Максимальное количество слушателей на одно EventTarget событие.
  • ...eventsTargets <EventTarget[]> | <EventEmitter[]> Ноль или более экземпляров <EventTarget> или <EventEmitter>. Если не указано, n устанавливается как значение по умолчанию для всех вновь созданных объектов <EventTarget> и <EventEmitter>.

Модули MJS

import { setMaxListeners, EventEmitter } from 'node:events';

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

setMaxListeners(5, target, emitter);

Модули CJS

const {
  setMaxListeners,
  EventEmitter,
} = require('node:events');

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

setMaxListeners(5, target, emitter);

events.addAbortListener(signal, resource)

Добавлена в: v18.18.0
Стабильность: 1 - Экспериментальная
  • signal <AbortSignal>
  • listener <Функция> | <Слушатель события>
  • Возвращает: <Утилизируемый>, который удаляет abort слушателя.

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

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

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

Возвращает объект disposable для более простого отписки.

Модули CJS

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]();
  }
}

Модули MJS

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

Модули MJS

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');
});

Модули CJS

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

eventemitterasyncresource.asyncId

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

eventemitterasyncresource.asyncResource

  • Тип: Базовый <AsyncResource>.

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

eventemitterasyncresource.emitDestroy()

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

eventemitterasyncresource.triggerAsyncId

  • Тип: <число> Тоже самое triggerAsyncId что передается конструктору AsyncResource.

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

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(), и 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 }); copy

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

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

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

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

В настоящее время ошибки сначала передаются в событие process.on('error') перед достижением process.on('uncaughtException'). Это поведение устарело и изменится в будущей версии для выравнивания EventTarget с другими API Node.js. Любой код, зависящий от события process.on('error'), должен быть выровнен с новым поведением.

Класс: Event

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

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

v14.5.0

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

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

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

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

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

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

event.cancelable
Добавлена в: v14.5.0
  • Тип: <boolean> Истинно, если событие было создано с опцией 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
Стабильность: 3 - Устаревшее: Используйте event.defaultPrevented вместо этого.
  • Тип: <boolean> Истинно, если событие не отменено.

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

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

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

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

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

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

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

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

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

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

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

Класс: EventTarget

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

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

v14.5.0

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

eventTarget.addEventListener(type, listener[, options])
История
Версия Изменения
v15.4.0

Добавлена поддержка параметра signal.

v14.5.0

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

  • type <string>
  • listener <Function> | <EventListener>
  • options <Object>
    • once <boolean> При true, обработчик автоматически удаляется после первого вызова. По умолчанию: false.
    • passive <boolean> При true, служит подсказкой, что обработчик не будет вызывать метод Event объекта preventDefault(). По умолчанию: 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 события или метод 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

Добавлен в: v18.7.0
Устойчивость: 1 - Экспериментально.
  • Расширяет: <Event>

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

event.detail
Добавлен в: v18.7.0
Устойчивость: 1 - Экспериментально.
  • Тип: <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-v18.x/docs/api/events.html

Spec-Zone.ru

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