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