Spec-Zone.ru › Node.js 20 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(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

Добавлен аргумент 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 <Функция> Функция обратного вызова
  • Возвращает: <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 <строка> | <символ> Название события.
  • listener <Функция> Функция-обработчик
  • Возвращает: <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 <строка> | <символ> Название события.
  • listener <Функция> Функция-обработчик
  • Возвращает: <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 <строка> | <символ>
  • Возвращает: <EventEmitter>

Удаляет все обработчики или только обработчики указанного события eventName.

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

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

emitter.removeListener(eventName, listener)

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

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

const callback = (stream) => {
  console.log('someone connected!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback); 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 <целое число>
  • Возвращает: <EventEmitter>

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

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

emitter.rawListeners(eventName)

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

Возвращает копию массива обработчиков для события с именем 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 <строка> | <символ>
  • ...args <любое>

Метод 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

Добавлен в: 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

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

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

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

events.getEventListeners(emitterOrTarget, eventName)

Добавлен в: 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)

Добавлен в: v19.9.0
  • emitterOrTarget <EventEmitter> | <EventTarget>
  • Возвращает: <число>

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

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

Для 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'));

Чтобы поймать оба события, создайте каждый из обещаний *до* ожидания любого из них, тогда станет возможным использовать 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)

Добавлен в: 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])

История
Версия Изменения
v20.13.0

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

v20.0.0

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

v13.6.0, v12.16.0

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

  • emitter <EventEmitter>
  • eventName <строка> | <символ> Имя события, на которое подписываются
  • options <Объект>
    • signal <AbortSignal> Может быть использован для отмены ожидания событий.
    • close - <Массив строк> Имена событий, которые завершат итерацию.
    • highWaterMark - <целое число> По умолчанию: Number.MAX_SAFE_INTEGER Верхний предел. Эмиттер приостанавливается каждый раз, когда размер буферизованных событий превышает его. Поддерживается только для эмиттеров, реализующих методы pause() и resume().
    • lowWaterMark - <целое число> По умолчанию: 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 <число> Неотрицательное число. Максимальное количество слушателей на 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
Уровень стабильности: 1 - Экспериментальная
  • signal <AbortSignal>
  • listener <Функция> | <Обработчик событий>
  • Возвращает: <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 операций, требующих ручного отслеживания асинхронности. В частности, все события, испускаемые экземплярами 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 хуки. Это должно вызываться только один раз. Будет выброшено исключение, если оно вызывается более одного раза. Это обязательно вызывать вручную. Если ресурс оставлен для сбора мусором GC, то 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> 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> EventTarget , отправляющий событие.

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

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

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

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

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

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

Маркер временной метки в миллисекундах, когда был создан объект 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, служит подсказкой, что обработчик не будет вызывать метод Event объекта preventDefault(). Значение по умолчанию: 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 события равно false или метод preventDefault() не был вызван, в противном случае false.

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

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

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

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

Класс: CustomEvent

История
Версия Изменения
v20.13.0

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

v18.7.0, v16.17.0

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

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

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

event.detail
История
Версия Изменения
v20.13.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 , эмулирующее эквивалентный API EventEmitter. Единственное отличие между 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/dist/latest-v20.x/docs/api/events.html

Spec-Zone.ru

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