Меню

Наследование от EventEmitter в NodeJs

30.06.2018 - Back-end, NodeJS

Extending Event Emitter

В реальном мире, довольно редко Вы будете работать с этим объектом — emitter напрямую. Вместо этого, Вы будете создавать класс, у которого будут все возможности EventEmitter, и потом вы будете использовать этот класс в своем коде. Давайте посмотрим что и почему. 😸

Давайте посмотрим на модуль logger.

var url = 'http://mylogger.io/log';

function log(message) {
    //Send an HTTP Request
    console.log(message);
}

module.exports.log = log;

В этом модуле мы экспортируем простую функцию log. Давайте в ней, после вывода в консоль сообщения добавим событие. И позже из app модуля мы будет слушать это событие, и что либо делать в ответ на него. Для начала добавим импорт модуля events в модуль logger. А также добавим поднятие события.

const EventEmitter = require('events');
const emitter = new EventEmitter();

var url = 'http://mylogger.io/log';

function log(message) {
    //Send an HTTP Request
    console.log(message);
    emitter.emit('messageLogged', {id: 1, url: 'http://'});
}

module.exports.log = log;

Теперь в модуле app мы загрузим модуль logger и вызовем функцию log.

//app.js
const EventEmitter = require('events');
const emitter = new EventEmitter();

emitter.on('messageLogged', arg => {
    console.log('Listener called', arg);
});

const log = require('./logger');
log('message');

Если мы сейчас запустим app, то наш слушатель не услышит событие и не выполнится. Сейчас посмотрим почему. Причина в том, что здесь мы работаем с двумя разными EventEmitters. В app.js свой объект emitter, а в logger другой. Ранее мы уже говорили, что класс, это как трафарет. А объект это экземпляр. Т.е. мы имеем дело с двумя разными объектами. В логгере, мы используем один объект чтобы поднять событие, а в app мы используем совсем другой объект, чтобы услышать событие.

Когда мы регистрируем слушатель, этот слушатель зарегистрирован только для этого EventEmitter. Который совершенно не тот, который находится в logger. Вот почему мы будем очень очень редко работать с EventEmitter напрямую. Вместо этого мы создадим класс, у которого будут все возможности EventEmitter, но будут также дополнительные возможности. В связи с чем, мы создадим класс Logger. У которого будует дополнительный метод log. Мы унаследуем этот класс от EventEmitter. Тем вызовем emit внутри метода log, через this.

const EventEmitter = require('events');

var url = 'http://mylogger.io/log';

class Logger extends EventEmitter {
    log(message) {
        //Send an HTTP Request
        console.log(message);
        //Raise an event
        this.emit('messageLogged', {
            id: 1,
            url: 'http://'
        });
    }
}
module.exports = Logger;

Теперь наведем некоторые изменения в нашем app модуле. Как видим, теперь мы импортируем в него наш класс Logger. И создаем его экземпляр. Далее мы как бы говорим: «Эй, логгер, когда ты поднимешь этот messageLogged событие, я хочу выполнить этот код: console.log('Listener called', arg);

const Logger = require('./logger');
const logger = new Logger();

logger.on('messageLogged', arg => {
    console.log('Listener called', arg);
});

logger.log('message');

Подведем итоги:
Когда вы хотите поднять событие в вашем приложении, чтобы подать сигнал, что что то случилось, Вам нужно создать класс, который наследуется от EventEmitter. К этому классу, который имеют всю функциональность EventEmitter, добавляется дополнительный функционал. В нашем случае есть способность выводить сообщения. И наконец, в app вместо использования экземпляра EventEmitter, мы будем использовать экземпляр кастомного класса, который определили и который наследуется от EventEmitter.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *