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