Перейти к содержанию

События

Для построения более гибкой и масштабируемой архитектуры приложения можно использовать Node.js события, которые представлены классом EventEmitter встроенного модуля events.

Перейдем сразу к примеру.

app.js

const EventEmitter = require('events')

const emitter = new EventEmitter()

emitter.on('message', message => console.log('Message: ', message))
emitter.on('error', error => console.log('Error: ', error))

emitter.emit('message', 'Node js EventEmitter in action.')

Генерация Node.js события осуществляется с помощью метода emit() объекта экземпляра класса EventEmitter, который первым аргументом принимает название события, а всеми необязательными остальными - передаваемые данные.

Обработчик регистрируется с использованием метода on(), которому передается два параметра:

  • имя Node.js события;
  • callback-функция, принимающая в качестве параметров указанные в emit() данные.

Если в процессе генерации события произойдет ошибка, то Node.js самостоятельно инициирует возникновение события error, и если для него не будет найден обработчик, то будет сгенерировано исключение.

Экземпляры EventEmitter

Обычно в приложении создаются несколько экземпляров класса EventEmitter для логического разграничения типов Node.js событий.

app.js

const EventEmitter = require('events')

class EmitterOne extends EventEmitter {}
class EmitterTwo extends EventEmitter {}

const emitterOneInstance = new EmitterOne()
const emitterTwoInstance = new EmitterTwo()

emitterOneInstance.on('message', message => console.log('Emitter one message: ', message))
emitterOneInstance.on('error', error => console.log('Emitter one error: ', error))

emitterTwoInstance.on('message', message => console.log('Emitter two message: ', message))
emitterTwoInstance.on('error', error => console.log('Emitter two error: ', error))

emitterOneInstance.emit('message', 'Node js EventEmitter in action.')

Работа напрямую с базовым классом EventEmitter будет регистрировать все обработчики глобально и при последующем создании нового экземпляра он унаследует все события базового класса. Поэтому работайте либо только с экземплярами, либо только с базовым классом.

EventEmitter API

Для однократного выполнения регистрируемого обработчика вместо метода on() используйте once(), который перед вызовом callback-функции удаляет его из памяти.

app.js

const EventEmitter = require('events')

const emitter = new EventEmitter()

emitter.once('message', message => console.log('Message: ', message)) //выполнится один раз

emitter.emit('message', 'First')
emitter.emit('message', 'Second')

По умолчанию для каждого отдельного события можно максимально зарегистрировать 10 функций обработчиков. Чтобы снять это ограничение для всех событий всех созданных экземпляров, измените значение свойства EventEmitter.defaultMaxListeners.

app.js

const EventEmitter = require('events')

EventEmitter.defaultMaxListeners = 1

const emitter = new EventEmitter()

emitter.on('message', message => console.log('Listener 1: ', message))
emitter.on('message', message => console.log('Listener 2: ', message))

emitter.emit('message', 'Message')

Чтобы изменить ограничение для отдельного экземпляра, используйте применительно к нему метод setMaxListeners().

const emitter = new EventEmitter()

emitter.setMaxListeners(1)

В случае превышения максимального количества обработчиков Node.js события будет выдано предупреждение.

Чтобы узнать, сколько обрабатывающих функций уже зарегистрировано на конкретное событие, используйте метод EventEmitter.listenerCount(), которому передаются два параметра:

  • экземпляр EventEmitter, относительно которого было зарегистрировано событие;
  • имя события.

app.js

const EventEmitter = require('events')

const emitter = new EventEmitter()

emitter.on('message', message => console.log('Listener 1: ', message))
emitter.on('message', message => console.log('Listener 2: ', message))

console.log(EventEmitter.listenerCount(emitter, 'message')) //2

Получить все зарегистрированные события позволяет метод eventNames().

emitter.on('message', message => console.log('Message: ', message))
emitter.on('error', error => console.log('Error: ', error))

console.log(emitter.eventNames()) //['message', 'error']

Для удаления определенного обработчика у отдельного события используйте метод removeListener(), принимающий в качестве параметров имя Node.js события и сам обработчик.

const messageListener = message => console.log('Message: ', message)

emitter.on('message', messageListener)

emitter.emit('message', 'First')

emitter.removeListener('message', messageListener)

emitter.emit('message', 'Second') //на этом этапе обработичка уже нет

Для удаления всех обработчиков события или сразу нескольких событий, используйте метод removeAllListeners(), который принимает массив событий, обработчики которых необходимо удалить.

const messageListener1 = message => console.log('Message listener 1: ', message)
const messageListener2 = message => console.log('Message listener 2: ', message)
const errorListener = error => console.log('Error: ', error)

emitter.on('message', messageListener1)
emitter.on('message', messageListener2)
emitter.on('error', errorListener)

emitter.emit('message', 'First')

emitter.removeAllListeners(['message'])

emitter.emit('message', 'Second') //на этом этапе обработичков уже нет