Одна из причин высокой скорости Node.js заключается в том, что он закодирован вокруг событий. Вместо того, чтобы читать все файлы, необходимые при каждом запросе (например, PHP), с помощью Node вы просто запускаете свой сервер, инициализируете большинство переменных, объявляете свои функции, а затем просто ждете, когда произойдет событие.
Хотя Node.js имеет несколько полезных встроенных событий, таких как событие запроса, разве не было бы полезно иметь возможность создавать наши собственные события и запускать их самостоятельно? Об этом я и поговорю в этой статье.
Сначала я покажу вам, как генерируются нормальные события. В качестве случая я возьму пример, когда человек входит в магазин, может прозвенеть звонок, чтобы показать его присутствие. Он будет немного похож на шаблон наблюдателя, где наше событие действует как субъект, а все функции, связанные с ним, похожи на наблюдателей. Итак, пример магазина:
var events = require('events'); var eventEmitter = new events.EventEmitter(); var ringBell = function ringBell() { console.log('ring ring ring'); } eventEmitter.on('doorOpen', ringBell); eventEmitter.emit('doorOpen');
Сначала мы загружаем модуль событий , который является частью ядра Node.js. Затем мы создаем новый экземпляр класса EventEmitter
(который мы собираемся расширить позже). После этого мы ringBell
функцию ringBell
в переменную, чтобы ее можно было вызывать таким образом. Он просто печатает ‘ring ring ring’ в нашей консоли.
Теперь интересные вещи идут. Мы добавляем нашу функцию ringBell
в список doorOpen
события doorOpen
. Это делается методом eventEmitter.on()
и в качестве первого аргумента события, в качестве второго аргумента добавляемой функции. Это на самом деле ничего не делает, просто регистрирует нашу функцию. Настоящее волшебство случается после того, как мы испустим наше событие. Вызов метода emit()
выполнит все функции, зарегистрированные с помощью метода on
.
Это не так интересно, можно было бы просто вызвать эту функцию, если бы мы хотели, чтобы прозвенел звонок. Но вот что делает события такими интересными: вы можете зарегистрировать столько функций, сколько захотите.
Мы могли бы также сделать это, например:
eventEmitter.on('doorOpen', ringBell); eventEmitter.on('doorOpen', doSomething); eventEmitter.on('doorOpen', doSomethingElse); eventEmitter.emit('doorOpen');
Это также будет работать и будет больше использовать функции, предоставляемые нам EventEmitter.
Мы также можем использовать функции с аргументами в качестве слушателей:
eventEmitter.on('doorOpen', function(ring) { Console.log(ring); } eventEmitter.emit('doorOpen', 'ringeling');
Мы просто передаем аргументы в методе emit()
.
Хотя все это очень мощно, в сообществе Node распространена практика наследования от класса eventEmitter. Мы могли бы сделать это, имея класс door, с методом open()
который будет doorOpen
событие doorOpen
. Посмотрите на этот код:
var events = require('events'); function Door(colour) { this.colour = colour; events.EventEmitter.call(this); this.open = function() { this.emit('open'); } } Door.prototype.__proto__ = events.EventEmitter.prototype; var frontDoor = new Door('brown'); frontDoor.on('open', function() { console.log('ring ring ring'); }); frontDoor.open();
В конструкторе нашего объекта Door
мы устанавливаем цвет двери и используем метод call()
нашего объекта EventEmitter, который выполняет метод конструктора EventEmitter. Затем мы объявляем наш метод open, который генерирует событие open. Эта строка:
Door.prototype.__proto__ = events.EventEmitter.prototype;
Копирует все свойства EventEmitter в объект Door.
Затем мы создаем нашу входную дверь, которая является экземпляром Door и имеет коричневый цвет. Затем мы добавляем прослушиватель событий и, наконец, открываем дверь и выводим сообщение на нашу консоль. Я надеюсь, что вы все видите, что этот модуль событий очень мощный и полезный!
Затем, наконец, модуль событий предоставляет нам список всех прослушивателей событий, прикрепленных к событию, и способ удаления прослушивателей событий.
var ring = function() { console.log('ring'); } frontDoor.on('open', ring); console.log(require('util').inspect(frontDoor.listeners('open'))); // Outputs ring
Вы можете сделать это с помощью свойства listeners
. Конечно, это работает, только если вы не использовали анонимную функцию в качестве прослушивателя событий.
Если бы мы захотели, мы могли бы убрать звонок из нашей двери:
frontDoor.removeListener('open', ring);
Или мы могли бы даже удалить всех слушателей:
frontDoor. .removeAllListeners('open');
Спасибо за чтение этого руководства, я надеюсь, что вы чему-то научились. Увидимся в следующий раз!