Spec-Zone.ru › Node.js

События

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

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

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

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

Все объекты, которые излучают события, являются экземплярами класса EventEmitter. Эти объекты предоставляют функцию eventEmitter.on(), которая позволяет прикрепить одну или несколько функций к именованным событиям, излучаемым объектом. Обычно имена событий — это строчные camelCase, но можно использовать любой допустимый ключ 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(shapeMode)]: false,
  //     [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(shapeMode)]: false,
  //     [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 undefined
});
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 <Функция> Функция-обработчик события

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

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

Тот факт, что событие срабатывает до добавления слушателя, имеет тонкий, но важный побочный эффект: любые дополнительные слушатели, зарегистрированные для того же name внутри обратного вызова '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 <Функция> Функция-обработчик события

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

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

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

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

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

v3.2.0

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

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

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

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

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

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 modules

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 modules

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 modules

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: v19.9.0, v18.17.0
  • emitterOrTarget <EventEmitter> | <EventTarget>
  • Возвращает: <число>

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

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

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

MJS modules

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 modules

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 modules

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 modules

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 modules

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 modules

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 modules

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 modules

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 modules

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 modules

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 modules

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 modules

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 modules

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

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

CJS modules

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

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

Поддержка highWaterMark и lowWaterMark параметров. Для согласованности. Старые параметры по-прежнему поддерживаются.

v20.0.0

Теперь поддерживаются параметры close, highWatermark, и lowWatermark.

v13.6.0, v12.16.0

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

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

Модули 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 <number> Неотрицательное число. Максимальное количество слушателей на событие 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, listener)

Добавлен в: v20.5.0, v18.18.0
Устойчивость: 1 - Экспериментально
  • signal <AbortSignal>
  • listener <Function> | <EventListener>
  • Возвращает: <Disposable> Disposable, который удаляет слушателя 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 , требующих ручного отслеживания async. В частности, все события, испускаемые экземплярами 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 <Object>
    • captureRejections <boolean> Включает автоматическое перехват отмены обещаний. По умолчанию: false.
    • name <string> Тип асинхронного события. По умолчанию: new.target.name.
    • triggerAsyncId <number> Идентификатор контекста выполнения, который создал это асинхронное событие. По умолчанию: executionAsyncId().
    • requireManualDestroy <boolean> Если установлено в true, отключает emitDestroy при сборе мусора объекта. Обычно это не нужно устанавливать (даже если emitDestroy вызывается вручную), если не извлекается asyncId ресурса и с ним не вызывается emitDestroy чувствительного API. При установке в false, вызов emitDestroy при сборе мусора будет выполнен только в том случае, если существует хотя бы один активный крючок destroy. По умолчанию: false.

eventemitterasyncresource.asyncId

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

eventemitterasyncresource.asyncResource

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

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

eventemitterasyncresource.emitDestroy()

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

eventemitterasyncresource.triggerAsyncId

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

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 обработка ошибок

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

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

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

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

Класс: Event

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

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

v14.5.0

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Избыточно с конструкторами событий и неспособна устанавливать composed. Это не используется в 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> True, если событие не отменено.

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

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

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

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

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

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

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

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

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

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

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

Класс: EventTarget

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

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

v14.5.0

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

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

Добавлена поддержка опции signal.

v14.5.0

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

  • type <строка>
  • listener <Функция> | <Обработчик события>
  • options <объект>
    • once <булево> Если true, обработчик автоматически удаляется после первого вызова. По умолчанию: false.
    • passive <булево> Если true, указывает, что обработчик не будет вызывать метод preventDefault() объекта Event. По умолчанию: false.
    • capture <булево> Не используется напрямую 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 <Событие>
  • Возвращает: <булево> true если значение атрибута cancelable события или вызов метода preventDefault() был ложным, в противном случае false.

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

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

eventTarget.removeEventListener(type, listener[, options])
Добавлена в: v14.5.0
  • type <строка>
  • listener <Функция> | <Обработчик события>
  • options <объект>
    • capture <булево>

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

Класс: CustomEvent

История
Версия Изменения
v22.1.0

CustomEvent теперь стабильна.

v18.7.0, v16.17.0

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

Устойчивость: 2 - Стабильно
  • Расширяет: <Событие>

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

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

CustomEvent теперь стабильна.

v18.7.0, v16.17.0

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

Устойчивость: 2 - Стабильно
  • Тип: <любой> Возвращает пользовательские данные, переданные при инициализации.

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

Класс: NodeEventTarget

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

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

nodeEventTarget.addListener(type, listener)
Добавлена в: v14.5.0
  • type <строка>

  • listener <Функция> | <Обработчик события>

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

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

nodeEventTarget.emit(type, arg)
Добавлена в: v15.2.0
  • type <строка>
  • arg <любой>
  • Возвращает: <булево> true если существуют зарегистрированные обработчики событий для type, иначе false.

Node.js-специфическое расширение класса EventTarget для отправки события arg в список обработчиков для type.

nodeEventTarget.eventNames()
Добавлена в: v14.5.0
  • Возвращает: <массив строк>

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

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

  • Возвращает: <число>

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

nodeEventTarget.setMaxListeners(n)
Добавлена в: v14.5.0
  • n <число>

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

nodeEventTarget.getMaxListeners()
Добавлена в: v14.5.0
  • Возвращает: <число>

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

nodeEventTarget.off(type, listener[, options])
Добавлена в: v14.5.0
  • type <строка>

  • listener <Функция> | <Обработчик события>

  • options <Объект>

    • capture <логическое значение>
  • Возвращает: <EventTarget> this

Расширение, специфичное для Node.js, псевдоним для eventTarget.removeEventListener().

nodeEventTarget.on(type, listener)
Добавлена в: v14.5.0
  • type <строка>

  • listener <Функция> | <Обработчик события>

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

Расширение, специфичное для Node.js, псевдоним для eventTarget.addEventListener().

nodeEventTarget.once(type, listener)
Добавлена в: v14.5.0
  • type <строка>

  • listener <Функция> | <Обработчик события>

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

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

nodeEventTarget.removeAllListeners([type])
Добавлена в: v14.5.0
  • type <строка>

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

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

nodeEventTarget.removeListener(type, listener[, options])
Добавлена в: v14.5.0
  • type <строка>

  • listener <Функция> | <Обработчик события>

  • options <Объект>

    • capture <логическое значение>
  • Возвращает: <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/api/events.html

Spec-Zone.ru

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