События
Исходный код: lib/events.js
Большая часть основного API Node.js построена на идиоматичной асинхронной событийно-ориентированной архитектуре, в которой объекты определённых типов (называемые «эмиттерами») генерируют именованные события, вызывающие Function объекты («обработчики событий»).
Например: объект net.Server генерирует событие каждый раз, когда к нему подключается узел; fs.ReadStream генерирует событие при открытии файла; поток генерирует событие каждый раз, когда данные становятся доступными для чтения.
Все объекты, генерирующие события, являются экземплярами класса EventEmitter. Эти объекты предоставляют функцию eventEmitter.on(), которая позволяет привязывать одну или несколько функций к именованным событиям, генерируемым объектом. Обычно имена событий представляют собой строки в стиле camelCase, но можно использовать любой допустимый ключ свойства JavaScript.
Когда объект EventEmitter генерирует событие, все функции, привязанные к этому событию, вызываются синхронно. Любые значения, возвращённые вызванными обработчиками событий, игнорируются и отбрасываются.
В следующем примере показан простой экземпляр EventEmitter с одним обработчиком событий. Для регистрации обработчиков событий используется метод eventEmitter.on(), а для вызова события — метод eventEmitter.emit().
Модули JavaScript
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('an event occurred!');
});
myEmitter.emit('event');CommonJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('an event occurred!');
});
myEmitter.emit('event');Передача аргументов и this обработчикам событий
Метод eventEmitter.emit() позволяет передавать обработчикам событий произвольный набор аргументов. Обратите внимание: при вызове обычной функции-обработчика стандартное ключевое слово this намеренно устанавливается так, чтобы ссылаться на экземпляр EventEmitter, к которому привязан обработчик.
Модули JavaScript
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', function(a, b) {
console.log(a, b, this, this === myEmitter);
// Prints:
// a b MyEmitter {
// _events: [Object: null prototype] { event: [Function (anonymous)] },
// _eventsCount: 1,
// _maxListeners: undefined,
// [Symbol(shapeMode)]: false,
// [Symbol(kCapture)]: false
// } true
});
myEmitter.emit('event', 'a', 'b');CommonJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', function(a, b) {
console.log(a, b, this, this === myEmitter);
// Prints:
// a b MyEmitter {
// _events: [Object: null prototype] { event: [Function (anonymous)] },
// _eventsCount: 1,
// _maxListeners: undefined,
// [Symbol(shapeMode)]: false,
// [Symbol(kCapture)]: false
// } true
});
myEmitter.emit('event', 'a', 'b');В качестве обработчиков событий можно использовать стрелочные функции ES6, однако в этом случае ключевое слово this больше не будет ссылаться на экземпляр EventEmitter:
Модули JavaScript
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
console.log(a, b, this);
// Prints: a b undefined
});
myEmitter.emit('event', 'a', 'b');CommonJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
console.log(a, b, this);
// Prints: a b {}
});
myEmitter.emit('event', 'a', 'b');Асинхронное и синхронное выполнение
Метод EventEmitter вызывает все обработчики событий синхронно, в порядке их регистрации. Это обеспечивает правильную последовательность событий и помогает избежать состояния гонки и логических ошибок. При необходимости функции-обработчики могут перейти к асинхронному режиму работы с помощью методов setImmediate() или process.nextTick():
Модули JavaScript
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
setImmediate(() => {
console.log('this happens asynchronously');
});
});
myEmitter.emit('event', 'a', 'b');CommonJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
setImmediate(() => {
console.log('this happens asynchronously');
});
});
myEmitter.emit('event', 'a', 'b');Однократная обработка событий
При регистрации обработчика с помощью метода eventEmitter.on() он вызывается каждый раз, когда генерируется именованное событие.
Модули JavaScript
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.on('event', () => {
console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Prints: 2CommonJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.on('event', () => {
console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Prints: 2С помощью метода eventEmitter.once() можно зарегистрировать обработчик, который будет вызван не более одного раза для определённого события. После генерации события обработчик удаляется из регистрации и затем вызывается.
Модули JavaScript
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.once('event', () => {
console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// IgnoredCommonJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.once('event', () => {
console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// IgnoredСобытия ошибок
При возникновении ошибки в экземпляре EventEmitter обычно генерируется событие 'error'. В Node.js такие события обрабатываются особым образом.
Если у EventEmitter нет хотя бы одного зарегистрированного обработчика события 'error', а событие 'error' генерируется, ошибка выбрасывается, выводится трассировка стека, а процесс Node.js завершается.
Модули JavaScript
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// Throws and crashes Node.jsCommonJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// Throws and crashes Node.jsЧтобы предотвратить аварийное завершение процесса Node.js, можно использовать модуль domain. (Однако обратите внимание, что модуль node:domain устарел.)
Рекомендуется всегда добавлять обработчики для событий 'error'.
Модули JavaScript
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('error', (err) => {
console.error('whoops! there was an error');
});
myEmitter.emit('error', new Error('whoops!'));
// Prints: whoops! there was an errorCommonJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('error', (err) => {
console.error('whoops! there was an error');
});
myEmitter.emit('error', new Error('whoops!'));
// Prints: whoops! there was an errorМожно отслеживать события 'error', не перехватывая генерируемую ошибку, зарегистрировав обработчик с помощью символа events.errorMonitor.
Модули JavaScript
import { EventEmitter, errorMonitor } from 'node:events';
const myEmitter = new EventEmitter();
myEmitter.on(errorMonitor, (err) => {
MyMonitoringTool.log(err);
});
myEmitter.emit('error', new Error('whoops!'));
// Still throws and crashes Node.jsCommonJS
const { EventEmitter, errorMonitor } = require('node:events');
const myEmitter = new EventEmitter();
myEmitter.on(errorMonitor, (err) => {
MyMonitoringTool.log(err);
});
myEmitter.emit('error', new Error('whoops!'));
// Still throws and crashes Node.jsПерехват отклонённых промисов
Использование функций async в обработчиках событий может привести к проблемам, поскольку в случае выброшенного исключения это может вызвать необработанное отклонение промиса:
Модули JavaScript
import { EventEmitter } from 'node:events';
const ee = new EventEmitter();
ee.on('something', async (value) => {
throw new Error('kaboom');
});CommonJS
const EventEmitter = require('node:events');
const ee = new EventEmitter();
ee.on('something', async (value) => {
throw new Error('kaboom');
});Параметр captureRejections в конструкторе EventEmitter или глобальная настройка изменяют это поведение, устанавливая обработчик .then(undefined, handler) для Promise. Этот обработчик асинхронно перенаправляет исключение в метод Symbol.for('nodejs.rejection'), если он существует, или в обработчик события 'error', если такого метода нет.
Модули JavaScript
import { EventEmitter } from 'node:events';
const ee1 = new EventEmitter({ captureRejections: true });
ee1.on('something', async (value) => {
throw new Error('kaboom');
});
ee1.on('error', console.log);
const ee2 = new EventEmitter({ captureRejections: true });
ee2.on('something', async (value) => {
throw new Error('kaboom');
});
ee2[Symbol.for('nodejs.rejection')] = console.log;CommonJS
const EventEmitter = require('node:events');
const ee1 = new EventEmitter({ captureRejections: true });
ee1.on('something', async (value) => {
throw new Error('kaboom');
});
ee1.on('error', console.log);
const ee2 = new EventEmitter({ captureRejections: true });
ee2.on('something', async (value) => {
throw new Error('kaboom');
});
ee2[Symbol.for('nodejs.rejection')] = console.log;Настройка events.captureRejections = true изменит значение по умолчанию для всех новых экземпляров EventEmitter.
Модули JavaScript
import { EventEmitter } from 'node:events';
EventEmitter.captureRejections = true;
const ee1 = new EventEmitter();
ee1.on('something', async (value) => {
throw new Error('kaboom');
});
ee1.on('error', console.log);CommonJS
const events = require('node:events');
events.captureRejections = true;
const ee1 = new events.EventEmitter();
ee1.on('something', async (value) => {
throw new Error('kaboom');
});
ee1.on('error', console.log);События 'error', генерируемые поведением captureRejections, не имеют обработчика перехвата, чтобы избежать бесконечных циклов ошибок: рекомендуется не использовать функции async в качестве обработчиков событий 'error'.
Класс: EventEmitter
Класс EventEmitter определён и предоставляется модулем node:events:
Модули JavaScript
import { EventEmitter } from 'node:events';CommonJS
const EventEmitter = require('node:events');Все экземпляры EventEmitter генерируют событие 'newListener' при добавлении новых обработчиков событий и 'removeListener' при удалении существующих обработчиков.
Поддерживаются следующие параметры:
-
captureRejections<boolean> Включает автоматический перехват отклонённых промисов. По умолчанию:false.
Событие: 'newListener'
-
eventName<string> | <symbol> Имя отслеживаемого события -
listener<Function> Функция-обработчик события
Экземпляр EventEmitter генерирует собственное событие 'newListener' до добавления обработчика в свой внутренний массив обработчиков.
Обработчикам, зарегистрированным для события 'newListener', передаются имя события и ссылка на добавляемый обработчик.
Тот факт, что событие вызывается до добавления обработчика, имеет тонкий, но важный побочный эффект: любые дополнительные обработчики, зарегистрированные для того же name внутри обратного вызова 'newListener', вставляются перед добавляемым в данный момент обработчиком.
Модули JavaScript
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
// Only do this once so we don't loop forever
myEmitter.once('newListener', (event, listener) => {
if (event === 'event') {
// Insert a new listener in front
myEmitter.on('event', () => {
console.log('B');
});
}
});
myEmitter.on('event', () => {
console.log('A');
});
myEmitter.emit('event');
// Prints:
// B
// ACommonJS
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'
-
eventName<string> | <symbol> Имя события -
listener<Function> Функция-обработчик события
Событие 'removeListener' генерируется после удаления listener.
emitter.addListener(eventName, listener)
-
eventName<string> | <symbol> -
listener<Function>
Псевдоним для emitter.on(eventName, listener).
emitter.emit(eventName[, ...args])
Синхронно вызывает все обработчики, зарегистрированные для события с именем eventName, в порядке их регистрации, передавая каждому указанные аргументы.
Возвращает true, если у события были обработчики, и false в противном случае.
Модули JavaScript
import { EventEmitter } from 'node:events';
const myEmitter = new EventEmitter();
// First listener
myEmitter.on('event', function firstListener() {
console.log('Helloooo! first listener');
});
// Second listener
myEmitter.on('event', function secondListener(arg1, arg2) {
console.log(`event with parameters ${arg1}, ${arg2} in second listener`);
});
// Third listener
myEmitter.on('event', function thirdListener(...args) {
const parameters = args.join(', ');
console.log(`event with parameters ${parameters} in third listener`);
});
console.log(myEmitter.listeners('event'));
myEmitter.emit('event', 1, 2, 3, 4, 5);
// Prints:
// [
// [Function: firstListener],
// [Function: secondListener],
// [Function: thirdListener]
// ]
// Helloooo! first listener
// event with parameters 1, 2 in second listener
// event with parameters 1, 2, 3, 4, 5 in third listenerCommonJS
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()
- Возвращает: <Array>
Возвращает массив со списком событий, для которых эмиттер зарегистрировал обработчики. Значениями массива являются строки или Symbol.
Модули JavaScript
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => {});
myEE.on('bar', () => {});
const sym = Symbol('symbol');
myEE.on(sym, () => {});
console.log(myEE.eventNames());
// Prints: [ 'foo', 'bar', Symbol(symbol) ]CommonJS
const EventEmitter = require('node:events');
const myEE = new EventEmitter();
myEE.on('foo', () => {});
myEE.on('bar', () => {});
const sym = Symbol('symbol');
myEE.on(sym, () => {});
console.log(myEE.eventNames());
// Prints: [ 'foo', 'bar', Symbol(symbol) ]
emitter.getMaxListeners()
- Возвращает: <integer>
Возвращает текущее максимальное число обработчиков для EventEmitter, которое задаётся методом emitter.setMaxListeners(n) или по умолчанию равно events.defaultMaxListeners.
emitter.listenerCount(eventName[, listener])
-
eventName<string> | <symbol> Имя отслеживаемого события -
listener<Function> Функция-обработчик события - Возвращает: <integer>
Возвращает число обработчиков, отслеживающих событие с именем eventName. Если указан listener, метод возвращает число его вхождений в список обработчиков события.
emitter.listeners(eventName)
-
eventName<string> | <symbol> - Возвращает: <Function[]>
Возвращает копию массива обработчиков события с именем eventName.
server.on('connection', (stream) => {
console.log('someone connected!');
});
console.log(util.inspect(server.listeners('connection')));
// Prints: [ [Function] ] copy
emitter.off(eventName, listener)
-
eventName<string> | <symbol> -
listener<Function> - Возвращает: <EventEmitter>
Псевдоним для emitter.removeListener().
emitter.on(eventName, listener)
-
eventName<string> | <symbol> Имя события. -
listener<Function> Функция обратного вызова - Возвращает: <EventEmitter>
Добавляет функцию listener в конец массива обработчиков события с именем eventName. Проверка на то, был ли уже добавлен listener, не выполняется. Несколько вызовов с одной и той же комбинацией eventName и listener приведут к тому, что listener будет добавлен и вызван несколько раз.
server.on('connection', (stream) => {
console.log('someone connected!');
}); copy Возвращает ссылку на EventEmitter, что позволяет объединять вызовы в цепочку.
По умолчанию обработчики событий вызываются в порядке их добавления. В качестве альтернативы для добавления обработчика в начало массива обработчиков можно использовать метод emitter.prependListener().
Модули JavaScript
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// aCommonJS
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)
-
eventName<string> | <symbol> Имя события. -
listener<Function> Функция обратного вызова - Возвращает: <EventEmitter>
Добавляет функцию listener, которая будет вызвана один раз для события с именем eventName. При следующем вызове eventName этот обработчик удаляется, а затем вызывается.
server.once('connection', (stream) => {
console.log('Ah, we have our first user!');
}); copy Возвращает ссылку на EventEmitter, что позволяет объединять вызовы в цепочку.
По умолчанию обработчики событий вызываются в порядке их добавления. В качестве альтернативы для добавления обработчика в начало массива обработчиков можно использовать метод emitter.prependOnceListener().
Модули JavaScript
import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.once('foo', () => console.log('a'));
myEE.prependOnceListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
// b
// aCommonJS
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)
-
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)
-
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])
-
eventName<string> | <symbol> - Возвращает: <EventEmitter>
Удаляет все обработчики событий или обработчики указанного eventName.
Удалять обработчики, добавленные в другом месте кода, не рекомендуется, особенно если экземпляр EventEmitter создан другим компонентом или модулем (например, сокетом или файловым потоком).
Возвращает ссылку на EventEmitter, что позволяет объединять вызовы в цепочку.
emitter.removeListener(eventName, listener)
-
eventName<string> | <symbol> -
listener<Function> - Возвращает: <EventEmitter>
Удаляет указанный listener из массива обработчиков события с именем eventName.
const callback = (stream) => {
console.log('someone connected!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback); copy removeListener() удаляет из массива обработчиков не более одного экземпляра обработчика. Если один и тот же обработчик был добавлен в массив несколько раз для указанного eventName, для удаления каждого экземпляра необходимо несколько раз вызвать removeListener().
После генерации события все привязанные к нему на момент генерации обработчики вызываются по порядку. Это означает, что вызовы removeListener() или removeAllListeners(), выполненные после генерации события и до завершения выполнения последнего обработчика, не удалят их из выполняющегося emit(). Последующие события обрабатываются ожидаемым образом.
Модули JavaScript
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
const callbackA = () => {
console.log('A');
myEmitter.removeListener('event', callbackB);
};
const callbackB = () => {
console.log('B');
};
myEmitter.on('event', callbackA);
myEmitter.on('event', callbackB);
// callbackA removes listener callbackB but it will still be called.
// Internal listener array at time of emit [callbackA, callbackB]
myEmitter.emit('event');
// Prints:
// A
// B
// callbackB is now removed.
// Internal listener array [callbackA]
myEmitter.emit('event');
// Prints:
// ACommonJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
const callbackA = () => {
console.log('A');
myEmitter.removeListener('event', callbackB);
};
const callbackB = () => {
console.log('B');
};
myEmitter.on('event', callbackA);
myEmitter.on('event', callbackB);
// callbackA removes listener callbackB but it will still be called.
// Internal listener array at time of emit [callbackA, callbackB]
myEmitter.emit('event');
// Prints:
// A
// B
// callbackB is now removed.
// Internal listener array [callbackA]
myEmitter.emit('event');
// Prints:
// AПоскольку обработчики хранятся во внутреннем массиве, этот вызов изменит индексы всех обработчиков, зарегистрированных после удаляемого обработчика. Это не повлияет на порядок вызова обработчиков, но означает, что любые копии массива обработчиков, возвращённые методом emitter.listeners(), потребуется создать заново.
Если одна функция несколько раз добавлена в качестве обработчика одного события (как в примере ниже), removeListener() удалит экземпляр, добавленный последним. В примере удаляется обработчик once('ping'):
Модули JavaScript
import { EventEmitter } from 'node:events';
const ee = new EventEmitter();
function pong() {
console.log('pong');
}
ee.on('ping', pong);
ee.once('ping', pong);
ee.removeListener('ping', pong);
ee.emit('ping');
ee.emit('ping');CommonJS
const EventEmitter = require('node:events');
const ee = new EventEmitter();
function pong() {
console.log('pong');
}
ee.on('ping', pong);
ee.once('ping', pong);
ee.removeListener('ping', pong);
ee.emit('ping');
ee.emit('ping');Возвращает ссылку на EventEmitter, что позволяет объединять вызовы в цепочку.
emitter.setMaxListeners(n)
-
n<integer> - Возвращает: <EventEmitter>
По умолчанию EventEmitters выводит предупреждение, если для одного события добавлено больше 10 обработчиков. Это полезное значение по умолчанию, помогающее обнаруживать утечки памяти. Метод emitter.setMaxListeners() позволяет изменить ограничение для конкретного экземпляра EventEmitter. Чтобы указать неограниченное число обработчиков, можно установить значение Infinity (или 0).
Возвращает ссылку на EventEmitter, что позволяет объединять вызовы в цепочку.
emitter.rawListeners(eventName)
-
eventName<string> | <symbol> - Возвращает: <Function[]>
Возвращает копию массива обработчиков события с именем eventName, включая все функции-обёртки (например, созданные методом .once()).
Модули JavaScript
import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.once('log', () => console.log('log once'));
// Returns a new Array with a function `onceWrapper` which has a property
// `listener` which contains the original listener bound above
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];
// Logs "log once" to the console and does not unbind the `once` event
logFnWrapper.listener();
// Logs "log once" to the console and removes the listener
logFnWrapper();
emitter.on('log', () => console.log('log persistently'));
// Will return a new Array with a single function bound by `.on()` above
const newListeners = emitter.rawListeners('log');
// Logs "log persistently" twice
newListeners[0]();
emitter.emit('log');CommonJS
const EventEmitter = require('node:events');
const emitter = new EventEmitter();
emitter.once('log', () => console.log('log once'));
// Returns a new Array with a function `onceWrapper` which has a property
// `listener` which contains the original listener bound above
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];
// Logs "log once" to the console and does not unbind the `once` event
logFnWrapper.listener();
// Logs "log once" to the console and removes the listener
logFnWrapper();
emitter.on('log', () => console.log('log persistently'));
// Will return a new Array with a single function bound by `.on()` above
const newListeners = emitter.rawListeners('log');
// Logs "log persistently" twice
newListeners[0]();
emitter.emit('log');
emitter[Symbol.for('nodejs.rejection')](err, eventName[, ...args])
Метод Symbol.for('nodejs.rejection') вызывается при отклонении промиса во время генерации события, если для эмиттера включён параметр captureRejections. Вместо Symbol.for('nodejs.rejection') можно использовать events.captureRejectionSymbol.
Модули JavaScript
import { EventEmitter, captureRejectionSymbol } from 'node:events';
class MyClass extends EventEmitter {
constructor() {
super({ captureRejections: true });
}
[captureRejectionSymbol](err, event, ...args) {
console.log('rejection happened for', event, 'with', err, ...args);
this.destroy(err);
}
destroy(err) {
// Tear the resource down here.
}
}CommonJS
const { EventEmitter, captureRejectionSymbol } = require('node:events');
class MyClass extends EventEmitter {
constructor() {
super({ captureRejections: true });
}
[captureRejectionSymbol](err, event, ...args) {
console.log('rejection happened for', event, 'with', err, ...args);
this.destroy(err);
}
destroy(err) {
// Tear the resource down here.
}
}
events.defaultMaxListeners
По умолчанию для любого отдельного события можно зарегистрировать не более 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() можно использовать, чтобы временно избежать этого предупреждения:
Модули JavaScript
import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.setMaxListeners(emitter.getMaxListeners() + 1);
emitter.once('event', () => {
// do stuff
emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0));
});CommonJS
const EventEmitter = require('node:events');
const emitter = new EventEmitter();
emitter.setMaxListeners(emitter.getMaxListeners() + 1);
emitter.once('event', () => {
// do stuff
emitter.setMaxListeners(Math.max(emitter.getMaxListeners() - 1, 0));
});Флаг командной строки --trace-warnings можно использовать для вывода трассировки стека таких предупреждений.
Сгенерированное предупреждение можно просмотреть с помощью process.on('warning'). Оно будет содержать дополнительные свойства emitter, type и count, указывающие соответственно на экземпляр эмиттера события, имя события и число привязанных обработчиков. Свойству name присваивается значение 'MaxListenersExceededWarning'.
events.errorMonitor
Этот символ следует использовать для установки прослушивателя, который только отслеживает события 'error'. Прослушиватели, установленные с помощью этого символа, вызываются перед обычными прослушивателями 'error'.
Установка прослушивателя с помощью этого символа не меняет поведение после генерации события 'error'. Поэтому процесс по-прежнему завершится аварийно, если не установлен обычный прослушиватель 'error'.
events.getEventListeners(emitterOrTarget, eventName)
-
emitterOrTarget<EventEmitter> | <EventTarget> -
eventName<string> | <symbol> - Возвращает: <Function[]>
Возвращает копию массива прослушивателей для события с именем eventName.
Для EventEmitters это работает точно так же, как вызов .listeners у эмиттера.
Для EventTargets это единственный способ получить прослушиватели событий для целевого объекта событий. Это полезно для отладки и диагностики.
Модули JavaScript
import { getEventListeners, EventEmitter } from 'node:events';
{
const ee = new EventEmitter();
const listener = () => console.log('Events are fun');
ee.on('foo', listener);
console.log(getEventListeners(ee, 'foo')); // [ [Function: listener] ]
}
{
const et = new EventTarget();
const listener = () => console.log('Events are fun');
et.addEventListener('foo', listener);
console.log(getEventListeners(et, 'foo')); // [ [Function: listener] ]
}CommonJS
const { getEventListeners, EventEmitter } = require('node:events');
{
const ee = new EventEmitter();
const listener = () => console.log('Events are fun');
ee.on('foo', listener);
console.log(getEventListeners(ee, 'foo')); // [ [Function: listener] ]
}
{
const et = new EventTarget();
const listener = () => console.log('Events are fun');
et.addEventListener('foo', listener);
console.log(getEventListeners(et, 'foo')); // [ [Function: listener] ]
}
events.getMaxListeners(emitterOrTarget)
-
emitterOrTarget<EventEmitter> | <EventTarget> - Возвращает: <number>
Возвращает текущее установленное максимальное количество прослушивателей.
Для EventEmitters это работает точно так же, как вызов .getMaxListeners у эмиттера.
Для EventTargets это единственный способ получить максимальное количество прослушивателей событий для целевого объекта событий. Если количество обработчиков событий для одного EventTarget превышает установленный максимум, EventTarget выведет предупреждение.
Модули JavaScript
import { getMaxListeners, setMaxListeners, EventEmitter } from 'node:events';
{
const ee = new EventEmitter();
console.log(getMaxListeners(ee)); // 10
setMaxListeners(11, ee);
console.log(getMaxListeners(ee)); // 11
}
{
const et = new EventTarget();
console.log(getMaxListeners(et)); // 10
setMaxListeners(11, et);
console.log(getMaxListeners(et)); // 11
}CommonJS
const { getMaxListeners, setMaxListeners, EventEmitter } = require('node:events');
{
const ee = new EventEmitter();
console.log(getMaxListeners(ee)); // 10
setMaxListeners(11, ee);
console.log(getMaxListeners(ee)); // 11
}
{
const et = new EventTarget();
console.log(getMaxListeners(et)); // 10
setMaxListeners(11, et);
console.log(getMaxListeners(et)); // 11
}
events.once(emitter, name[, options])
-
emitter<EventEmitter> -
name<string> | <symbol> -
options<Object>-
signal<AbortSignal> Можно использовать для отмены ожидания события.
-
- Возвращает: <Promise>
Создаёт Promise, который выполняется при генерации EventEmitter заданного события или отклоняется, если во время ожидания EventEmitter генерирует 'error'. Promise разрешится массивом всех аргументов, переданных при генерации заданного события.
Этот метод намеренно является обобщённым и работает с интерфейсом EventTarget веб-платформы, у которого нет особой семантики событий 'error' и который не прослушивает событие 'error'.
Модули JavaScript
import { once, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
process.nextTick(() => {
ee.emit('myevent', 42);
});
const [value] = await once(ee, 'myevent');
console.log(value);
const err = new Error('kaboom');
process.nextTick(() => {
ee.emit('error', err);
});
try {
await once(ee, 'myevent');
} catch (err) {
console.error('error happened', err);
}CommonJS
const { once, EventEmitter } = require('node:events');
async function run() {
const ee = new EventEmitter();
process.nextTick(() => {
ee.emit('myevent', 42);
});
const [value] = await once(ee, 'myevent');
console.log(value);
const err = new Error('kaboom');
process.nextTick(() => {
ee.emit('error', err);
});
try {
await once(ee, 'myevent');
} catch (err) {
console.error('error happened', err);
}
}
run();Особая обработка события 'error' применяется только при использовании events.once() для ожидания другого события. Если events.once() используется для ожидания самого события 'error', оно обрабатывается как событие любого другого типа, без особой обработки:
Модули JavaScript
import { EventEmitter, once } from 'node:events';
const ee = new EventEmitter();
once(ee, 'error')
.then(([err]) => console.log('ok', err.message))
.catch((err) => console.error('error', err.message));
ee.emit('error', new Error('boom'));
// Prints: ok boomCommonJS
const { EventEmitter, once } = require('node:events');
const ee = new EventEmitter();
once(ee, 'error')
.then(([err]) => console.log('ok', err.message))
.catch((err) => console.error('error', err.message));
ee.emit('error', new Error('boom'));
// Prints: ok boomДля отмены ожидания события можно использовать <AbortSignal>:
Модули JavaScript
import { EventEmitter, once } from 'node:events';
const ee = new EventEmitter();
const ac = new AbortController();
async function foo(emitter, event, signal) {
try {
await once(emitter, event, { signal });
console.log('event emitted!');
} catch (error) {
if (error.name === 'AbortError') {
console.error('Waiting for the event was canceled!');
} else {
console.error('There was an error', error.message);
}
}
}
foo(ee, 'foo', ac.signal);
ac.abort(); // Prints: Waiting for the event was canceled!CommonJS
const { EventEmitter, once } = require('node:events');
const ee = new EventEmitter();
const ac = new AbortController();
async function foo(emitter, event, signal) {
try {
await once(emitter, event, { signal });
console.log('event emitted!');
} catch (error) {
if (error.name === 'AbortError') {
console.error('Waiting for the event was canceled!');
} else {
console.error('There was an error', error.message);
}
}
}
foo(ee, 'foo', ac.signal);
ac.abort(); // Prints: Waiting for the event was canceled!Ожидание нескольких событий, сгенерированных при process.nextTick()
При использовании функции events.once() для ожидания нескольких событий, сгенерированных в одной и той же группе операций process.nextTick(), а также при синхронной генерации нескольких событий, следует учитывать один особый случай. В частности, поскольку очередь process.nextTick() опустошается до очереди микрозадач Promise, а EventEmitter синхронно генерирует все события, events.once() может пропустить событие.
Модули JavaScript
import { EventEmitter, once } from 'node:events';
import process from 'node:process';
const myEE = new EventEmitter();
async function foo() {
await once(myEE, 'bar');
console.log('bar');
// This Promise will never resolve because the 'foo' event will
// have already been emitted before the Promise is created.
await once(myEE, 'foo');
console.log('foo');
}
process.nextTick(() => {
myEE.emit('bar');
myEE.emit('foo');
});
foo().then(() => console.log('done'));CommonJS
const { EventEmitter, once } = require('node:events');
const myEE = new EventEmitter();
async function foo() {
await once(myEE, 'bar');
console.log('bar');
// This Promise will never resolve because the 'foo' event will
// have already been emitted before the Promise is created.
await once(myEE, 'foo');
console.log('foo');
}
process.nextTick(() => {
myEE.emit('bar');
myEE.emit('foo');
});
foo().then(() => console.log('done'));Чтобы получить оба события, создайте каждый из объектов Promise до ожидания любого из них. После этого можно использовать Promise.all(), Promise.race() или Promise.allSettled():
Модули JavaScript
import { EventEmitter, once } from 'node:events';
import process from 'node:process';
const myEE = new EventEmitter();
async function foo() {
await Promise.all([once(myEE, 'bar'), once(myEE, 'foo')]);
console.log('foo', 'bar');
}
process.nextTick(() => {
myEE.emit('bar');
myEE.emit('foo');
});
foo().then(() => console.log('done'));CommonJS
const { EventEmitter, once } = require('node:events');
const myEE = new EventEmitter();
async function foo() {
await Promise.all([once(myEE, 'bar'), once(myEE, 'foo')]);
console.log('foo', 'bar');
}
process.nextTick(() => {
myEE.emit('bar');
myEE.emit('foo');
});
foo().then(() => console.log('done'));
events.captureRejections
Значение: <boolean>
Изменяет значение параметра captureRejections по умолчанию для всех новых объектов EventEmitter.
events.captureRejectionSymbol
Значение: Symbol.for('nodejs.rejection')
См. инструкции по написанию пользовательского обработчика отклонения.
events.listenerCount(emitter, eventName)
emitter.listenerCount().-
emitter<EventEmitter> Эмиттер для запроса -
eventName<string> | <symbol> Имя события
Метод класса, возвращающий количество прослушивателей заданного eventName, зарегистрированных у заданного emitter.
Модули JavaScript
import { EventEmitter, listenerCount } from 'node:events';
const myEmitter = new EventEmitter();
myEmitter.on('event', () => {});
myEmitter.on('event', () => {});
console.log(listenerCount(myEmitter, 'event'));
// Prints: 2CommonJS
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])
-
emitter<EventEmitter> -
eventName<string> | <symbol> Имя прослушиваемого события -
options<Object>-
signal<AbortSignal> Можно использовать для отмены ожидания событий. -
close— <string[]> Имена событий, завершающих итерацию. -
highWaterMark— <integer> По умолчанию:Number.MAX_SAFE_INTEGERВерхний порог. Эмиттер приостанавливается каждый раз, когда размер буферизованных событий превышает это значение. Поддерживается только эмиттерами, реализующими методыpause()иresume(). -
lowWaterMark— <integer> По умолчанию:1Нижний порог. Эмиттер возобновляет работу каждый раз, когда размер буферизованных событий становится меньше этого значения. Поддерживается только эмиттерами, реализующими методыpause()иresume().
-
- Возвращает: <AsyncIterator>, выполняющий итерацию по событиям
eventName, сгенерированнымemitter
Модули JavaScript
import { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo')) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable hereCommonJS
const { on, EventEmitter } = require('node:events');
(async () => {
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo')) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
})();Возвращает AsyncIterator, выполняющий итерацию по событиям eventName. Если EventEmitter генерирует 'error', будет выброшено исключение. При выходе из цикла удаляются все прослушиватели. value, возвращаемый на каждой итерации, представляет собой массив аргументов сгенерированного события.
Для отмены ожидания событий можно использовать <AbortSignal>:
Модули JavaScript
import { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ac = new AbortController();
(async () => {
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo', { signal: ac.signal })) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
})();
process.nextTick(() => ac.abort());CommonJS
const { on, EventEmitter } = require('node:events');
const ac = new AbortController();
(async () => {
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo', { signal: ac.signal })) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
})();
process.nextTick(() => ac.abort());
events.setMaxListeners(n[, ...eventTargets])
-
n<number> Неотрицательное число. Максимальное количество прослушивателей для каждого событияEventTarget. -
...eventsTargets<EventTarget[]> | <EventEmitter[]> Ноль или более экземпляров <EventTarget> или <EventEmitter>. Если экземпляры не указаны,nустанавливается в качестве максимального значения по умолчанию для всех вновь созданных объектов <EventTarget> и <EventEmitter>.
Модули JavaScript
import { setMaxListeners, EventEmitter } from 'node:events';
const target = new EventTarget();
const emitter = new EventEmitter();
setMaxListeners(5, target, emitter);CommonJS
const {
setMaxListeners,
EventEmitter,
} = require('node:events');
const target = new EventTarget();
const emitter = new EventEmitter();
setMaxListeners(5, target, emitter);
events.addAbortListener(signal, listener)
-
signal<AbortSignal> -
listener<Function> | <EventListener> - Возвращает: <Disposable> Объект Disposable, удаляющий прослушиватель
abort.
Однократно прослушивает событие abort у предоставленного signal.
Прослушивание события abort у сигналов отмены небезопасно и может привести к утечкам ресурсов, поскольку другая сторонняя сторона, использующая сигнал, может вызвать e.stopImmediatePropagation(). К сожалению, Node.js не может изменить это поведение, поскольку оно нарушило бы веб-стандарт. Кроме того, исходный API позволяет легко забыть удалить прослушиватели.
Этот API позволяет безопасно использовать AbortSignal в API Node.js, устраняя обе эти проблемы: событие прослушивается таким образом, что stopImmediatePropagation не препятствует вызову прослушивателя.
Возвращается объект disposable, чтобы упростить отмену подписки.
CommonJS
const { addAbortListener } = require('node:events');
function example(signal) {
let disposable;
try {
signal.addEventListener('abort', (e) => e.stopImmediatePropagation());
disposable = addAbortListener(signal, (e) => {
// Do something when signal is aborted.
});
} finally {
disposable?.[Symbol.dispose]();
}
}Модули JavaScript
import { addAbortListener } from 'node:events';
function example(signal) {
let disposable;
try {
signal.addEventListener('abort', (e) => e.stopImmediatePropagation());
disposable = addAbortListener(signal, (e) => {
// Do something when signal is aborted.
});
} finally {
disposable?.[Symbol.dispose]();
}
}Класс: events.EventEmitterAsyncResource extends EventEmitter
Интегрирует EventEmitter с <AsyncResource> для EventEmitter, которым требуется ручное отслеживание асинхронных операций. В частности, все события, генерируемые экземплярами events.EventEmitterAsyncResource, выполняются в их асинхронном контексте.
Модули JavaScript
import { EventEmitterAsyncResource, EventEmitter } from 'node:events';
import { notStrictEqual, strictEqual } from 'node:assert';
import { executionAsyncId, triggerAsyncId } from 'node:async_hooks';
// Async tracking tooling will identify this as 'Q'.
const ee1 = new EventEmitterAsyncResource({ name: 'Q' });
// 'foo' listeners will run in the EventEmitters async context.
ee1.on('foo', () => {
strictEqual(executionAsyncId(), ee1.asyncId);
strictEqual(triggerAsyncId(), ee1.triggerAsyncId);
});
const ee2 = new EventEmitter();
// 'foo' listeners on ordinary EventEmitters that do not track async
// context, however, run in the same async context as the emit().
ee2.on('foo', () => {
notStrictEqual(executionAsyncId(), ee2.asyncId);
notStrictEqual(triggerAsyncId(), ee2.triggerAsyncId);
});
Promise.resolve().then(() => {
ee1.emit('foo');
ee2.emit('foo');
});CommonJS
const { EventEmitterAsyncResource, EventEmitter } = require('node:events');
const { notStrictEqual, strictEqual } = require('node:assert');
const { executionAsyncId, triggerAsyncId } = require('node:async_hooks');
// Async tracking tooling will identify this as 'Q'.
const ee1 = new EventEmitterAsyncResource({ name: 'Q' });
// 'foo' listeners will run in the EventEmitters async context.
ee1.on('foo', () => {
strictEqual(executionAsyncId(), ee1.asyncId);
strictEqual(triggerAsyncId(), ee1.triggerAsyncId);
});
const ee2 = new EventEmitter();
// 'foo' listeners on ordinary EventEmitters that do not track async
// context, however, run in the same async context as the emit().
ee2.on('foo', () => {
notStrictEqual(executionAsyncId(), ee2.asyncId);
notStrictEqual(triggerAsyncId(), ee2.triggerAsyncId);
});
Promise.resolve().then(() => {
ee1.emit('foo');
ee2.emit('foo');
});Класс EventEmitterAsyncResource имеет те же методы и принимает те же параметры, что и EventEmitter и AsyncResource.
new events.EventEmitterAsyncResource([options])
-
options<Object>-
captureRejections<boolean> Включает автоматический перехват отклонения Promise. По умолчанию: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. Этот метод следует вызывать только один раз. При повторном вызове будет выброшена ошибка. Его необходимо вызвать вручную. Если ресурс будет собран сборщиком мусора, хуки destroy вызваны не будут.
eventemitterasyncresource.triggerAsyncId
- Тип: <number> То же значение
triggerAsyncId, которое передаётся конструкторуAsyncResource.
API EventTarget и Event
Объекты EventTarget и Event представляют собой специфичную для Node.js реализацию веб-API EventTarget, доступную в некоторых основных API Node.js.
const target = new EventTarget();
target.addEventListener('foo', (event) => {
console.log('foo event happened!');
}); copy EventTarget Node.js и EventTarget DOM
Между EventTarget Node.js и веб-API EventTarget есть два ключевых различия:
- В то время как экземпляры
EventTargetDOM могут образовывать иерархию, в Node.js нет понятия иерархии и распространения событий. То есть событие, отправленное объектуEventTarget, не распространяется по иерархии вложенных целевых объектов, каждый из которых может иметь собственный набор обработчиков события. - В
EventTargetNode.js, если слушатель события является асинхронной функцией или возвращаетPromise, а возвращённыйPromiseотклоняется, отклонение автоматически перехватывается и обрабатывается так же, как слушатель, который выбрасывает исключение синхронно (подробности см. в разделе Обработка ошибокEventTarget).
NodeEventTarget и EventEmitter
Объект NodeEventTarget реализует изменённое подмножество API EventEmitter, позволяющее ему в определённых ситуациях точно имитировать EventEmitter. NodeEventTarget не является экземпляром EventEmitter и в большинстве случаев не может использоваться вместо EventEmitter.
- В отличие от
EventEmitter, любойlistenerможно зарегистрировать для одного событияtypeне более одного раза. Повторные попытки регистрацииlistenerигнорируются. NodeEventTargetне имитирует весь APIEventEmitter. В частности, APIprependListener(),prependOnceListener(),rawListeners()иerrorMonitorне имитируются. События'newListener'и'removeListener'также не генерируются.NodeEventTargetне реализует особое поведение по умолчанию для событий с типом'error'.NodeEventTargetподдерживает в качестве обработчиков для всех типов событий как объектыEventListener, так и функции.
Слушатель события
Слушатели событий, зарегистрированные для события type, могут быть функциями JavaScript или объектами со свойством handleEvent, значением которого является функция.
В обоих случаях функция-обработчик вызывается с аргументом event, переданным функции eventTarget.dispatchEvent().
В качестве слушателей событий можно использовать асинхронные функции. Если асинхронная функция-обработчик отклоняет Promise, отклонение перехватывается и обрабатывается, как описано в разделе обработки ошибок EventTarget.
Исключение, выброшенное одной функцией-обработчиком, не препятствует вызову остальных обработчиков.
Возвращаемое значение функции-обработчика игнорируется.
Обработчики всегда вызываются в порядке их добавления.
Функции-обработчики могут изменять объект event.
function handler1(event) {
console.log(event.type); // Prints 'foo'
event.a = 1;
}
async function handler2(event) {
console.log(event.type); // Prints 'foo'
console.log(event.a); // Prints 1
}
const handler3 = {
handleEvent(event) {
console.log(event.type); // Prints 'foo'
},
};
const handler4 = {
async handleEvent(event) {
console.log(event.type); // Prints 'foo'
},
};
const target = new EventTarget();
target.addEventListener('foo', handler1);
target.addEventListener('foo', handler2);
target.addEventListener('foo', handler3);
target.addEventListener('foo', handler4, { once: true }); copy
Обработка ошибок EventTarget
Если зарегистрированный слушатель события выбрасывает исключение (или возвращает отклонённый Promise), по умолчанию ошибка считается необработанным исключением в process.nextTick(). Это означает, что необработанные исключения в EventTarget по умолчанию завершают процесс Node.js.
Исключение, выброшенное в слушателе события, не препятствует вызову других зарегистрированных обработчиков.
EventTarget не реализует специальную обработку по умолчанию для событий типа 'error', например EventEmitter.
В настоящее время ошибки сначала перенаправляются в событие process.on('error'), а затем передаются в process.on('uncaughtException'). Это поведение устарело и в одном из будущих выпусков будет изменено, чтобы привести EventTarget в соответствие с другими API Node.js. Любой код, зависящий от события process.on('error'), следует привести в соответствие с новым поведением.
Класс: Event
Объект Event представляет собой адаптацию веб-API Event. Экземпляры создаются внутри Node.js.
event.bubbles
- Тип: <boolean> Всегда возвращает
false.
В Node.js это свойство не используется и предоставлено исключительно для полноты реализации.
event.cancelBubble
event.stopPropagation().- Тип: <boolean>
Синоним event.stopPropagation(), если установлено значение true. В Node.js это свойство не используется и предоставлено исключительно для полноты реализации.
event.cancelable
- Тип: <boolean> Значение True, если событие было создано с параметром
cancelable.
event.composed
- Тип: <boolean> Всегда возвращает
false.
В Node.js это свойство не используется и предоставлено исключительно для полноты реализации.
event.composedPath()
Возвращает массив, содержащий текущий EventTarget в качестве единственного элемента, или пустой массив, если событие не отправляется. В Node.js это свойство не используется и предоставлено исключительно для полноты реализации.
event.currentTarget
- Тип: <EventTarget> Объект
EventTarget, отправляющий событие.
Синоним event.target.
event.defaultPrevented
- Тип: <boolean>
Имеет значение true, если cancelable равно true и был вызван event.preventDefault().
event.eventPhase
- Тип: <number> Возвращает
0, если событие не отправляется, и2, если оно отправляется.
В Node.js это свойство не используется и предоставлено исключительно для полноты реализации.
event.initEvent(type[, bubbles[, cancelable]])
Избыточен при наличии конструкторов событий и не позволяет установить composed. В Node.js этот метод не используется и предоставлен исключительно для полноты реализации.
event.isTrusted
- Тип: <boolean>
Событие "abort" объекта <AbortSignal> генерируется со значением isTrusted, равным true. Во всех остальных случаях значение равно false.
event.preventDefault()
Устанавливает свойство defaultPrevented в значение true, если cancelable равно true.
event.returnValue
event.defaultPrevented.- Тип: <boolean> Значение True, если событие не было отменено.
Значение event.returnValue всегда противоположно значению event.defaultPrevented. В Node.js это свойство не используется и предоставлено исключительно для полноты реализации.
event.srcElement
event.target.- Тип: <EventTarget> Объект
EventTarget, отправляющий событие.
Синоним event.target.
event.stopImmediatePropagation()
Прекращает вызов слушателей событий после завершения работы текущего слушателя.
event.stopPropagation()
В Node.js этот метод не используется и предоставлен исключительно для полноты реализации.
event.target
- Тип: <EventTarget> Объект
EventTarget, отправляющий событие.
event.timeStamp
- Тип: <number>
Временная метка в миллисекундах, когда был создан объект Event.
event.type
- Тип: <string>
Идентификатор типа события.
Класс: EventTarget
eventTarget.addEventListener(type, listener[, options])
-
type<string> -
listener<Function> | <EventListener> -
options<Object>-
once<boolean> Еслиtrue, слушатель автоматически удаляется после первого вызова. По умолчанию:false. -
passive<boolean> Еслиtrue, служит подсказкой о том, что слушатель не будет вызывать методpreventDefault()объектаEvent. По умолчанию:false. -
capture<boolean> Напрямую не используется Node.js. Добавлен для полноты API. По умолчанию:false. -
signal<AbortSignal> Слушатель будет удалён при вызове методаabort()указанного объекта AbortSignal.
-
Добавляет новый обработчик события type. Любой заданный listener добавляется только один раз для каждой пары type и значения параметра capture.
Если параметр once имеет значение true, listener удаляется после следующей отправки события type.
Параметр capture не используется Node.js для каких-либо функциональных целей, кроме отслеживания зарегистрированных слушателей событий в соответствии со спецификацией EventTarget. В частности, параметр capture используется как часть ключа при регистрации listener. Каждый отдельный listener можно добавить один раз с capture = false и один раз с capture = true.
function handler(event) {}
const target = new EventTarget();
target.addEventListener('foo', handler, { capture: true }); // first
target.addEventListener('foo', handler, { capture: false }); // second
// Removes the second instance of handler
target.removeEventListener('foo', handler);
// Removes the first instance of handler
target.removeEventListener('foo', handler, { capture: true }); copy
eventTarget.dispatchEvent(event)
-
event<Event> - Возвращает: <boolean>
true, если значение атрибутаcancelableсобытия равно false или его методpreventDefault()не был вызван; в противном случаеfalse.
Отправляет event списку обработчиков для event.type.
Зарегистрированные слушатели событий вызываются синхронно в порядке регистрации.
eventTarget.removeEventListener(type, listener[, options])
-
type<string> -
listener<Function> | <EventListener> -
options<Object>-
capture<boolean>
-
Удаляет listener из списка обработчиков события type.
Класс: CustomEvent
- Расширяет: <Event>
Объект CustomEvent представляет собой адаптацию веб-API CustomEvent. Экземпляры создаются внутри Node.js.
event.detail
- Тип: <any> Возвращает пользовательские данные, переданные при инициализации.
Только для чтения.
Класс: NodeEventTarget
- Расширяет: <EventTarget>
NodeEventTarget — специфичное для Node.js расширение EventTarget, имитирующее подмножество API EventEmitter.
nodeEventTarget.addListener(type, listener)
-
type<string> -
listener<Function> | <EventListener> -
Возвращает: <EventTarget> this
Специфичное для Node.js расширение класса EventTarget, имитирующее соответствующий API EventEmitter. Единственное различие между addListener() и addEventListener() заключается в том, что addListener() возвращает ссылку на EventTarget.
nodeEventTarget.emit(type, arg)
-
type<string> -
arg<any> - Возвращает: <boolean>
true, если существуют слушатели событий, зарегистрированные дляtype; в противном случаеfalse.
Специфичное для Node.js расширение класса EventTarget, отправляющее arg списку обработчиков для type.
nodeEventTarget.eventNames()
- Возвращает: <string[]>
Специфичное для Node.js расширение класса EventTarget, возвращающее массив имён событий type, для которых зарегистрированы слушатели.
nodeEventTarget.listenerCount(type)
Специфичное для Node.js расширение класса EventTarget, возвращающее количество слушателей событий, зарегистрированных для type.
nodeEventTarget.setMaxListeners(n)
-
n<number>
Специфичное для Node.js расширение класса EventTarget, устанавливающее максимальное количество слушателей событий равным n.
nodeEventTarget.getMaxListeners()
- Возвращает: <number>
Специфичное для Node.js расширение класса EventTarget, возвращающее максимальное количество слушателей событий.
nodeEventTarget.off(type, listener[, options])
-
type<string> -
listener<Function> | <EventListener> -
options<Object>-
capture<boolean>
-
-
Возвращает: <EventTarget> this
Специфичный для Node.js синоним eventTarget.removeEventListener().
nodeEventTarget.on(type, listener)
-
type<string> -
listener<Function> | <EventListener> -
Возвращает: <EventTarget> this
Специфичный для Node.js синоним eventTarget.addEventListener().
nodeEventTarget.once(type, listener)
-
type<string> -
listener<Function> | <EventListener> -
Возвращает: <EventTarget> this
Специфичное для Node.js расширение класса EventTarget, добавляющее слушатель once для указанного события type. Это эквивалентно вызову on с параметром once, установленным в true.
nodeEventTarget.removeAllListeners([type])
-
type<string> -
Возвращает: <EventTarget> this
Специфичное для Node.js расширение класса EventTarget. Если указан type, удаляет все зарегистрированные слушатели для type; в противном случае удаляет все зарегистрированные слушатели.
nodeEventTarget.removeListener(type, listener[, options])
-
type<string> -
listener<Function> | <EventListener> -
options<Object>-
capture<boolean>
-
-
Возвращает: <EventTarget> this
Специфичное для Node.js расширение класса EventTarget, удаляющее listener для указанного type. Единственное различие между removeListener() и removeEventListener() заключается в том, что removeListener() возвращает ссылку на EventTarget.
© Joyent, Inc. and other Node contributors
Licensed under the MIT License.
Node.js is a trademark of Joyent, Inc. and is used with its permission.
We are not endorsed by or affiliated with Joyent.
https://nodejs.org/dist/latest-v20.x/docs/api/events.html