Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

696
Visualizações
Creating a Singleton EventEmittor in Nodejs & Express Project

I'm trying to create a Publisher-Subscriber pattern with Nodejs eventEmitters for my nodejs/express API project. My use-case is fairly simple:

  1. I want to emit events from various places in my project. For example, emit an event when a new user is created.
  2. Then I want a single place, where I listen to all the events and decide what actions to take.

This will require a singleton instance of eventEmitter because 'emit' and 'on' calls should happen on the same instance of 'event' object.

To achieve it, this is how my index.js looks:

const express = require('express')
const app = express()

const bodyParser = require('body-parser')
const routes = require('./api/routes')
const EventEmitter = require("events");
const eventEmitter = new EventEmitter();

const eventListeners = require('../src/subscribers/events');
//const eventSubs = new eventListeners();

app.use(eventListeners.eventSubscribers());

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.set('eventEmitter', eventEmitter);

app.get('/', (req, res) => res.send('App is working'))

app.use('/api', routes)

app.listen(3000, () => console.log('Example app listening on port 3000!'))

module.exports = {
  app
}

This is how my middleware/controller function looks(where I'm emitting event):

const createUser = async (req, res, next) => {
  var user = req.body
  try {
    console.log('in controller');

    await newUser(user)

    console.log(req.app.get('eventEmitter'));

    req.app.get('eventEmitter').emit('USER_CREATED', {email: user.email, name: user.name})

    res.status(200).send({success: true});
    next()

  } catch(e) {
    console.log(e.message)
    res.sendStatus(500) && next(e)
  }
}

And, this is how my event subscriber file looks:

const eventSubscribers = (req) => {
    const eventEmitter = req.app.get('eventEmitter');

    eventEmitter.on('USER_CREATED', ({ email, name }) => {
        console.log('event fired and captured')
    })
}

Using this, the event is getting emitted, but the event subscriber is not getting trigerred. I think there is something wrong with the way I'm accessing req/app objects in my subscriber. Also, I'm getting

TypeError: eventListeners.eventSubscribers is not a function

error in my index.js file. Questions I have:

  1. Is this the right way to create a publisher/subscriber pattern?
  2. How do I access req/app object instances in my event subscriber?
  3. What's the best way to make sure event subscriber file is loaded when the app loads?
over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

Assuming everything else is correctly setup by you,
I think the cause of the error that you mentioned

TypeError: eventListeners.eventSubscribers is not a function

is that no function is passed to the middleware i.e as a middleware, shouldn't you just pass the eventListeners.eventSubscribers like this

app.use(eventListeners.eventSubscribers);

instead of like this

app.use(eventListeners.eventSubscribers());

If we compare both expressions above, express is not able to pass the request object in the second case as you are calling it but this function call is returning nothing to the express i.e kind of void, but in first case since you passed the function object reference to express, it then calls it as middleware(as a callback later and passes the request object in it while calling it).

Alternatively I think you don't need to use middleware for using the EventEmitter, you can just keep a single global custom instance consisting of EventEmitter as it's property and all the different event you want to listen, and then just use them wherever you require them.You can use the EventEmitter as a property of this custom to emit event in whatever module you want to by importing this custom module there.

This is the working example below

index.js file/entry file

const express = require('express')
const app = express()
const bodyParser = require('body-parser')
const routes = require("./userRoute");
//const eventSubs = new eventListeners();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));

app.get('/', (req, res) => res.send('App is working'))

app.use('/api', routes);

app.listen(3000, () => console.log('Example app listening on port 3000!'))

This is our global singleton custom instance using EventEmitter as a property.

const { EventEmitter } = require("events");

class CustomEventEmitter {

    eventEmitter;

    constructor() {
        this.eventEmitter = new EventEmitter();
        this.initialize();
    }

    getEventEmitter() {
        return this.eventEmitter;
    }

    initialize() {
        this.eventEmitter.on('USER_CREATED', ({ email, name }) => {
            console.log('event fired and captured with data', email, name);
        });
    }
}

module.exports = new CustomEventEmitter();

and here we use our global CustomEventEmitter module in our request routes i.e userRoute.js

const router = require("express").Router();
const customEventEmitter = require("./CustomEventEmitter");

const createUser = async (req, res, next) => {
    var user = req.body
    try {
        console.log('in controller');

        // await newUser(user)

        customEventEmitter.getEventEmitter().emit('USER_CREATED', { email: user.email, name: user.name })

        res.status(200).send({ success: true });
        next()

    } catch (e) {
        console.log(e.message)
        res.sendStatus(500) && next(e)
    }
}

router.post("/createUser", createUser)

module.exports = router;
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda