javascript - 在 Node Js 和 Express 项目中创建单例 EventEmitter

标签 javascript node.js express eventemitter

我正在尝试使用 Nodejs eventEmitters 为我的 nodejs/express API 项目创建一个发布者-订阅者模式。我的用例相当简单:

  • 我想从项目中的各个地方发出事件。例如,在创建新用户时发出事件。
  • 然后我想要一个单一的地方,在那里我听所有的事件并决定采取什么行动。

  • 这将需要 eventEmitter 的单例实例,因为“emit”和“on”调用应该发生在“event”对象的同一个实例上。
    为了实现它,这就是我的 index.js 看起来:
    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
    }
    
    这就是我的中间件/ Controller 函数外观(我在哪里发出事件):
    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)
      }
    }
    
    而且,这就是我的事件订阅者 文件看起来:
    const eventSubscribers = (req) => {
        const eventEmitter = req.app.get('eventEmitter');
    
        eventEmitter.on('USER_CREATED', ({ email, name }) => {
            console.log('event fired and captured')
        })
    }
    
    使用它,事件被发出,但事件订阅者没有被触发。我认为我在订阅者中访问 req/app 对象的方式有问题。另外,我越来越
    TypeError: eventListeners.eventSubscribers is not a function
    
    我的 index.js 文件中的错误。我的问题:
  • 这是创建发布者/订阅者模式的正确方法吗?
  • 如何在我的事件订阅者中访问 req/app 对象实例?
  • 确保在应用加载时加载事件订阅者文件的最佳方法是什么?
  • 最佳答案

    假设您正确设置了其他所有内容,
    我认为你提到的错误的原因

    TypeError: eventListeners.eventSubscribers is not a function
    
    是没有函数传递给中间件,即作为中间件,你不应该像这样传递 eventListeners.eventSubscribers
    app.use(eventListeners.eventSubscribers);
    
    而不是这样
    app.use(eventListeners.eventSubscribers());
    
    如果我们比较上面的两个表达式,express 无法在第二种情况下传递请求对象,因为您正在调用它,但是这个函数调用没有返回 express 的任何内容,即某种 void,但在第一种情况下,因为您传递了函数对象引用 express,然后将其作为中间件调用(稍后作为回调并在调用时将请求对象传递给其中)。
    或者我认为你不需要使用中间件来使用 EventEmitter,你可以只保留一个由 EventEmitter 组成的全局自定义实例作为它的属性和你想要监听的所有不同事件,然后在你需要的地方使用它们.您可以使用 EventEmitter 作为此自定义的属性,通过在此处导入此自定义模块来在您想要的任何模块中发出事件。
    这是下面的工作示例
    index.js 文件/入口文件
    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!'))
    
    这是我们使用 EventEmitter 作为属性的全局单例自定义实例。
    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();
    
    在这里,我们在请求路由中使用我们的全局 CustomEventEmitter 模块
    即 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;
    

    关于javascript - 在 Node Js 和 Express 项目中创建单例 EventEmitter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65651829/

    相关文章:

    javascript - Firebase 云 Firestore + 身份验证 : write only for signed in users

    javascript - 异步 Lambda 函数 : Returning promise or sending responseURL does not terminate CloudFormation custom resource invocation

    node.js - 如何在 Node.js 中使用相同的键设置多个 http header 字段?

    javascript - 访问req.user将id保存到mongoDB

    javascript - 这是防止 JavaScript 中命名空间污染的好方法吗?

    javascript - 提示与 Window.prompt

    node.js - getById() 返回未定义的 Promise

    angularjs - 服务器/客户端的 Git 架构不错吗?

    node.js - Mongoose 不保存循环中的所有文档

    javascript - 类函数中 php 的轻松迭代