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