События
Исходный код: lib/events.js
Большая часть ядра Node.js API построена вокруг идиоматичной асинхронной архитектуры, управляемой событиями, в которой определенные типы объектов (называемые «эмиттерами») излучают именованные события, вызывающие Function объекты («слушатели»).
Например: объект net.Server излучает событие каждый раз, когда к нему подключается узел; объект fs.ReadStream излучает событие при открытии файла; поток stream излучает событие всякий раз, когда доступны данные для чтения.
Все объекты, которые излучают события, являются экземплярами класса EventEmitter. Эти объекты предоставляют функцию eventEmitter.on(), которая позволяет присоединить одну или несколько функций к именованным событиям, излучаемым объектом. Обычно имена событий являются строками с верблюжьим регистром, но можно использовать любой допустимый ключ свойства JavaScript.
Когда объект EventEmitter излучает событие, все функции, присоединенные к этому конкретному событию, вызываются синхронно. Любые значения, возвращаемые вызываемыми слушателями, игнорируются и отбрасываются.
Следующий пример демонстрирует простой экземпляр EventEmitter с одним слушателем. Метод eventEmitter.on() используется для регистрации слушателей, а метод eventEmitter.emit() используется для запуска события.
Модули MJS
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('an event occurred!');
});
myEmitter.emit('event');
Модули CJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', () => {
console.log('an event occurred!');
});
myEmitter.emit('event'); Передача аргументов и this слушателям
Метод eventEmitter.emit() позволяет передавать произвольное количество аргументов функциям-слушателям. Имейте в виду, что при вызове обычной функции-слушателя стандартное ключевое слово this преднамеренно устанавливается для ссылки на экземпляр EventEmitter, к которому прикреплен слушатель.
Модули MJS
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', function(a, b) {
console.log(a, b, this, this === myEmitter);
// Prints:
// a b MyEmitter {
// _events: [Object: null prototype] { event: [Function (anonymous)] },
// _eventsCount: 1,
// _maxListeners: undefined,
// [Symbol(shapeMode)]: false,
// [Symbol(kCapture)]: false
// } true
});
myEmitter.emit('event', 'a', 'b');
Модули CJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', function(a, b) {
console.log(a, b, this, this === myEmitter);
// Prints:
// a b MyEmitter {
// _events: [Object: null prototype] { event: [Function (anonymous)] },
// _eventsCount: 1,
// _maxListeners: undefined,
// [Symbol(shapeMode)]: false,
// [Symbol(kCapture)]: false
// } true
});
myEmitter.emit('event', 'a', 'b'); Возможно использовать стрелочные функции ES6 в качестве слушателей, однако в этом случае ключевое слово this больше не будет ссылаться на экземпляр EventEmitter.
Модули MJS
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
console.log(a, b, this);
// Prints: a b undefined
});
myEmitter.emit('event', 'a', 'b');
Модули CJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
console.log(a, b, this);
// Prints: a b {}
});
myEmitter.emit('event', 'a', 'b'); Асинхронные против синхронных
Метод EventEmitter вызывает всех слушателей синхронно в порядке их регистрации. Это гарантирует правильную последовательность событий и помогает избежать гонок и логических ошибок. При необходимости функции-слушатели могут переключиться на асинхронный режим работы, используя методы setImmediate() или process.nextTick().
Модули MJS
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
setImmediate(() => {
console.log('this happens asynchronously');
});
});
myEmitter.emit('event', 'a', 'b');
Модули CJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('event', (a, b) => {
setImmediate(() => {
console.log('this happens asynchronously');
});
});
myEmitter.emit('event', 'a', 'b'); Обработка событий только один раз
Когда слушатель регистрируется с помощью метода eventEmitter.on(), этот слушатель вызывается каждый раз при излучении именованного события.
Модули MJS
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.on('event', () => {
console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Prints: 2
Модули CJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.on('event', () => {
console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Prints: 2 С помощью метода eventEmitter.once() можно зарегистрировать слушатель, который вызывается не более одного раза для конкретного события. После излучения события слушатель отменяется и затем вызывается.
Модули MJS
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.once('event', () => {
console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Ignored
Модули CJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
let m = 0;
myEmitter.once('event', () => {
console.log(++m);
});
myEmitter.emit('event');
// Prints: 1
myEmitter.emit('event');
// Ignored События ошибок
При возникновении ошибки внутри экземпляра EventEmitter обычно излучается событие 'error'. Эти события обрабатываются как особые случаи в Node.js.
Если у экземпляра EventEmitter нет хотя бы одного зарегистрированного слушателя для события 'error', и излучается событие 'error', ошибка будет выброшена, будет напечатан стек вызовов, и процесс Node.js завершится.
Модули MJS
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// Throws and crashes Node.js
Модули CJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.emit('error', new Error('whoops!'));
// Throws and crashes Node.js Для предотвращения аварийного завершения процесса Node.js можно использовать модуль domain. (Обратите внимание, что модуль node:domain устарел.)
В качестве рекомендации слушатели всегда должны добавляться для событий 'error'.
Модули MJS
import { EventEmitter } from 'node:events';
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('error', (err) => {
console.error('whoops! there was an error');
});
myEmitter.emit('error', new Error('whoops!'));
// Prints: whoops! there was an error
Модули CJS
const EventEmitter = require('node:events');
class MyEmitter extends EventEmitter {}
const myEmitter = new MyEmitter();
myEmitter.on('error', (err) => {
console.error('whoops! there was an error');
});
myEmitter.emit('error', new Error('whoops!'));
// Prints: whoops! there was an error Можно отслеживать события 'error' без потребления излучаемой ошибки, установив слушателя с помощью символа events.errorMonitor.
Модули MJS
import { EventEmitter, errorMonitor } from 'node:events';
const myEmitter = new EventEmitter();
myEmitter.on(errorMonitor, (err) => {
MyMonitoringTool.log(err);
});
myEmitter.emit('error', new Error('whoops!'));
// Still throws and crashes Node.js
Модули CJS
const { EventEmitter, errorMonitor } = require('node:events');
const myEmitter = new EventEmitter();
myEmitter.on(errorMonitor, (err) => {
MyMonitoringTool.log(err);
});
myEmitter.emit('error', new Error('whoops!'));
// Still throws and crashes Node.js Перехват отклонений обещаний
Использование async функций с обработчиками событий проблематично, так как это может привести к необработанному отклонению в случае выброшенной ошибки:
Модули MJS
import { EventEmitter } from 'node:events';
const ee = new EventEmitter();
ee.on('something', async (value) => {
throw new Error('kaboom');
});
Модули CJS
const EventEmitter = require('node:events');
const ee = new EventEmitter();
ee.on('something', async (value) => {
throw new Error('kaboom');
}); Опция captureRejections в конструкторе EventEmitter или глобальная настройка меняют это поведение, устанавливая обработчик .then(undefined, handler) для Promise. Этот обработчик асинхронно перенаправляет исключение в метод Symbol.for('nodejs.rejection'), если он существует, или в обработчик события 'error', если его нет.
Модули MJS
import { EventEmitter } from 'node:events';
const ee1 = new EventEmitter({ captureRejections: true });
ee1.on('something', async (value) => {
throw new Error('kaboom');
});
ee1.on('error', console.log);
const ee2 = new EventEmitter({ captureRejections: true });
ee2.on('something', async (value) => {
throw new Error('kaboom');
});
ee2[Symbol.for('nodejs.rejection')] = console.log;
Модули CJS
const EventEmitter = require('node:events');
const ee1 = new EventEmitter({ captureRejections: true });
ee1.on('something', async (value) => {
throw new Error('kaboom');
});
ee1.on('error', console.log);
const ee2 = new EventEmitter({ captureRejections: true });
ee2.on('something', async (value) => {
throw new Error('kaboom');
});
ee2[Symbol.for('nodejs.rejection')] = console.log; Установка events.captureRejections = true изменит значение по умолчанию для всех новых экземпляров EventEmitter.
Модули MJS
import { EventEmitter } from 'node:events';
EventEmitter.captureRejections = true;
const ee1 = new EventEmitter();
ee1.on('something', async (value) => {
throw new Error('kaboom');
});
ee1.on('error', console.log);
Модули CJS
const events = require('node:events');
events.captureRejections = true;
const ee1 = new events.EventEmitter();
ee1.on('something', async (value) => {
throw new Error('kaboom');
});
ee1.on('error', console.log); События 'error', генерируемые поведением captureRejections, не имеют обработчика catch, чтобы избежать бесконечных циклов ошибок: рекомендуется не использовать async функции в качестве обработчиков событий 'error'.
Класс: EventEmitter
Класс 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, в порядке их регистрации, передавая предоставленные аргументы каждому.
Возвращает 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<Функция> Функция обратного вызова - Возвращает: <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<строка> | <символ> Название события. -
listener<Функция> Функция-обработчик - Возвращает: <EventEmitter>
Добавляет функцию listener в начало массива обработчиков для события с именем eventName. Не проверяется, был ли обработчик listener уже добавлен. Несколько вызовов с одинаковым сочетанием eventName и listener приведут к добавлению и вызову listener несколько раз.
server.prependListener('connection', (stream) => {
console.log('someone connected!');
}); copy Возвращает ссылку на EventEmitter, чтобы вызовы можно было объединить.
emitter.prependOnceListener(eventName, listener)
-
eventName<строка> | <символ> Название события. -
listener<Функция> Функция-обработчик - Возвращает: <EventEmitter>
Добавляет одноразовую listener функцию для события с именем eventName в начало массива обработчиков. При следующем срабатывании eventName, этот обработчик будет удалён, а затем вызван.
server.prependOnceListener('connection', (stream) => {
console.log('Ah, we have our first user!');
}); copy Возвращает ссылку на EventEmitter, чтобы вызовы можно было объединить.
emitter.removeAllListeners([eventName])
-
eventName<строка> | <символ> - Возвращает: <EventEmitter>
Удаляет все обработчики или только обработчики указанного события eventName.
Не рекомендуется удалять обработчики, добавленные в другом месте кода, особенно если экземпляр EventEmitter был создан другим компонентом или модулем (например, сокетами или потоками файлов).
Возвращает ссылку на EventEmitter, чтобы вызовы можно было объединить.
emitter.removeListener(eventName, listener)
-
eventName<строка> | <символ> -
listener<Функция> - Возвращает: <EventEmitter>
Удаляет указанный listener из массива обработчиков события с именем eventName.
const callback = (stream) => {
console.log('someone connected!');
};
server.on('connection', callback);
// ...
server.removeListener('connection', callback); 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<целое число> - Возвращает: <EventEmitter>
По умолчанию EventEmitter выведет предупреждение, если для конкретного события будет добавлено более 10 обработчиков. Это полезный параметр по умолчанию, который помогает находить утечки памяти. Метод emitter.setMaxListeners() позволяет изменить предел для этого конкретного экземпляра EventEmitter. Значение может быть установлено в Infinity (или 0) для указания неограниченного числа обработчиков.
Возвращает ссылку на EventEmitter, чтобы вызовы можно было объединить.
emitter.rawListeners(eventName)
-
eventName<строка> | <символ> - Возвращает: <Функция[]>
Возвращает копию массива обработчиков для события с именем eventName, включая все обертки (например, те, которые созданы .once()).
Модули MJS
import { EventEmitter } from 'node:events';
const emitter = new EventEmitter();
emitter.once('log', () => console.log('log once'));
// Returns a new Array with a function `onceWrapper` which has a property
// `listener` which contains the original listener bound above
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];
// Logs "log once" to the console and does not unbind the `once` event
logFnWrapper.listener();
// Logs "log once" to the console and removes the listener
logFnWrapper();
emitter.on('log', () => console.log('log persistently'));
// Will return a new Array with a single function bound by `.on()` above
const newListeners = emitter.rawListeners('log');
// Logs "log persistently" twice
newListeners[0]();
emitter.emit('log');
Модули CJS
const EventEmitter = require('node:events');
const emitter = new EventEmitter();
emitter.once('log', () => console.log('log once'));
// Returns a new Array with a function `onceWrapper` which has a property
// `listener` which contains the original listener bound above
const listeners = emitter.rawListeners('log');
const logFnWrapper = listeners[0];
// Logs "log once" to the console and does not unbind the `once` event
logFnWrapper.listener();
// Logs "log once" to the console and removes the listener
logFnWrapper();
emitter.on('log', () => console.log('log persistently'));
// Will return a new Array with a single function bound by `.on()` above
const newListeners = emitter.rawListeners('log');
// Logs "log persistently" twice
newListeners[0]();
emitter.emit('log');
emitter[Symbol.for('nodejs.rejection')](err, eventName[, ...args])
Метод 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 это единственный способ получить максимальное количество обработчиков событий для целевого объекта события. Если количество обработчиков событий в одном целевом объекте превышает заданное максимальное значение, целевой объект выведет предупреждение.
Модули 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')); Чтобы поймать оба события, создайте каждый из обещаний *до* ожидания любого из них, тогда станет возможным использовать 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> Может быть использован для отмены ожидания событий. -
close- <Массив строк> Имена событий, которые завершат итерацию. -
highWaterMark- <целое число> По умолчанию:Number.MAX_SAFE_INTEGERВерхний предел. Эмиттер приостанавливается каждый раз, когда размер буферизованных событий превышает его. Поддерживается только для эмиттеров, реализующих методыpause()иresume(). -
lowWaterMark- <целое число> По умолчанию:1Нижний предел. Эмиттер возобновляется каждый раз, когда размер буферизованных событий ниже его. Поддерживается только для эмиттеров, реализующих методыpause()иresume().
-
- Возвращает: <AsyncIterator> которая итерирует
eventNameсобытия, излучаемыеemitter
Модули MJS
import { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo')) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
Модули CJS
const { on, EventEmitter } = require('node:events');
(async () => {
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo')) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
})(); Возвращает AsyncIterator, который итерирует eventName события. Выбросит исключение, если EventEmitter излучит 'error'. Удаляет все обработчики при выходе из цикла. value , возвращаемый каждой итерацией, представляет собой массив, составленный из аргументов излученного события.
Для отмены ожидания событий можно использовать <AbortSignal>:
Модули MJS
import { on, EventEmitter } from 'node:events';
import process from 'node:process';
const ac = new AbortController();
(async () => {
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo', { signal: ac.signal })) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
})();
process.nextTick(() => ac.abort());
Модули CJS
const { on, EventEmitter } = require('node:events');
const ac = new AbortController();
(async () => {
const ee = new EventEmitter();
// Emit later on
process.nextTick(() => {
ee.emit('foo', 'bar');
ee.emit('foo', 42);
});
for await (const event of on(ee, 'foo', { signal: ac.signal })) {
// The execution of this inner block is synchronous and it
// processes one event at a time (even with await). Do not use
// if concurrent execution is required.
console.log(event); // prints ['bar'] [42]
}
// Unreachable here
})();
process.nextTick(() => ac.abort());
events.setMaxListeners(n[, ...eventTargets])
-
n<число> Неотрицательное число. Максимальное количество слушателей наEventTargetсобытие. -
...eventsTargets<EventTarget[]> | <EventEmitter[]> Ноль или более экземпляров <EventTarget> или <EventEmitter>. Если не указано,nустанавливается в качестве значения по умолчанию для всех вновь созданных объектов <EventTarget> и <EventEmitter>.
Модули MJS
import { setMaxListeners, EventEmitter } from 'node:events';
const target = new EventTarget();
const emitter = new EventEmitter();
setMaxListeners(5, target, emitter);
Модули CJS
const {
setMaxListeners,
EventEmitter,
} = require('node:events');
const target = new EventTarget();
const emitter = new EventEmitter();
setMaxListeners(5, target, emitter);
events.addAbortListener(signal, listener)
-
signal<AbortSignal> -
listener<Функция> | <Обработчик событий> - Возвращает: <Disposable> Disposable, который удаляет
abortслушателя.
Слушает событие abort один раз на предоставленном signal.
Прослушивание события abort на сигналах прерывания небезопасно и может привести к утечкам ресурсов, так как другая третья сторона с сигналом может вызвать e.stopImmediatePropagation(). К сожалению, Node.js не может изменить это, так как это нарушит веб-стандарт. Кроме того, исходный API делает легко забыть об удалении слушателей.
Этот API позволяет безопасно использовать AbortSignal в API Node.js, решив эти две проблемы, прослушивая событие таким образом, чтобы stopImmediatePropagation не препятствовал выполнению слушателя.
Возвращает объект Disposable, чтобы его было проще отписаться.
Модули CJS
const { addAbortListener } = require('node:events');
function example(signal) {
let disposable;
try {
signal.addEventListener('abort', (e) => e.stopImmediatePropagation());
disposable = addAbortListener(signal, (e) => {
// Do something when signal is aborted.
});
} finally {
disposable?.[Symbol.dispose]();
}
}
Модули MJS
import { addAbortListener } from 'node:events';
function example(signal) {
let disposable;
try {
signal.addEventListener('abort', (e) => e.stopImmediatePropagation());
disposable = addAbortListener(signal, (e) => {
// Do something when signal is aborted.
});
} finally {
disposable?.[Symbol.dispose]();
}
} Класс: events.EventEmitterAsyncResource extends EventEmitter
Интегрирует 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извлекается, и чувствительный APIemitDestroyвызывается с ним. При установке в значениеfalse, вызовemitDestroyпри сборе мусора произойдёт только если есть хотя бы один активныйdestroyхук. По умолчанию:false.
-
eventemitterasyncresource.asyncId
- Тип: <число> Уникальный
asyncIdназначенный ресурсу.
eventemitterasyncresource.asyncResource
- Тип: Базовый <AsyncResource>.
Возвращаемый AsyncResource объект имеет дополнительное свойство eventEmitter, которое предоставляет ссылку на этот EventEmitterAsyncResource.
eventemitterasyncresource.emitDestroy()
Вызывает все destroy хуки. Это должно вызываться только один раз. Будет выброшено исключение, если оно вызывается более одного раза. Это обязательно вызывать вручную. Если ресурс оставлен для сбора мусором GC, то destroy хуки никогда не будут вызваны.
eventemitterasyncresource.triggerAsyncId
- Тип: <число> То же
triggerAsyncId, что передаётся конструкторуAsyncResource.
EventTarget и Event API
Объекты 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> 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>
EventTarget, отправляющий событие.
Псевдоним для event.target.
event.stopImmediatePropagation()
Останавливает вызов обработчиков событий после завершения текущего.
event.stopPropagation()
Этот метод не используется в Node.js и предоставлен исключительно для полноты API.
event.target
- Тип: <EventTarget> Объект
EventTarget, который обрабатывает событие.
event.timeStamp
- Тип: <число>
Маркер временной метки в миллисекундах, когда был создан объект Event .
event.type
- Тип: <строка>
Идентификатор типа события.
Класс: EventTarget
eventTarget.addEventListener(type, listener[, options])
-
type<строка> -
listener<Функция> | <ОбработчикСобытия> -
options<Объект>-
once<логическое значение> Приtrue, обработчик автоматически удаляется при первом вызове. Значение по умолчанию:false. -
passive<логическое значение> Приtrue, служит подсказкой, что обработчик не будет вызывать методEventобъектаpreventDefault(). Значение по умолчанию:false. -
capture<логическое значение> Не используется напрямую в Node.js. Добавлено для полноты API. Значение по умолчанию:false. -
signal<AbortSignal> Обработчик будет удален при вызове методаabort()объекта AbortSignal.
-
Добавляет новый обработчик для события type . Любой заданный listener добавляется только один раз на type и для каждого значения параметра capture.
Если параметр once имеет значение true, обработчик listener удаляется после следующего вызова события type.
Параметр capture не используется Node.js функционально, кроме отслеживания зарегистрированных обработчиков событий в соответствии со спецификацией EventTarget. В частности, параметр capture используется в качестве части ключа при регистрации listener. Любой отдельный listener может быть добавлен один раз с capture = false, и один раз с capture = true.
function handler(event) {}
const target = new EventTarget();
target.addEventListener('foo', handler, { capture: true }); // first
target.addEventListener('foo', handler, { capture: false }); // second
// Removes the second instance of handler
target.removeEventListener('foo', handler);
// Removes the first instance of handler
target.removeEventListener('foo', handler, { capture: true }); copy
eventTarget.dispatchEvent(event)
-
event<Событие> - Возвращает: <логическое значение>
true, если значение атрибутаcancelableсобытия равно false или методpreventDefault()не был вызван, в противном случаеfalse.
Отправляет событие event в список обработчиков для event.type.
Зарегистрированные обработчики событий вызываются синхронно в порядке их регистрации.
eventTarget.removeEventListener(type, listener[, options])
-
type<строка> -
listener<Функция> | <ОбработчикСобытия> -
options<Объект>-
capture<логическое значение>
-
Удаляет обработчик listener из списка обработчиков для события type.
Класс: CustomEvent
- Расширяет: <Событие>
Объект CustomEvent — адаптация CustomEvent API Веб-стандартов. Экземпляры создаются внутри Node.js.
event.detail
- Тип: <любой> Возвращает пользовательские данные, переданные при инициализации.
Только чтение.
Класс: NodeEventTarget
- Расширяет: <EventTarget>
NodeEventTarget — Node.js-специфическое расширение EventTarget , эмулирующее подмножество API EventEmitter.
nodeEventTarget.addListener(type, listener)
-
type<строка> -
listener<Функция> | <ОбработчикСобытия> -
Возвращает: <EventTarget> this
Node.js-специфическое расширение класса EventTarget , эмулирующее эквивалентный API EventEmitter. Единственное отличие между 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/dist/latest-v20.x/docs/api/events.html