Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/377.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在Nodejs中创建单例eventemitter&;快速项目_Javascript_Node.js_Express_Eventemitter - Fatal编程技术网

Javascript 在Nodejs中创建单例eventemitter&;快速项目

Javascript 在Nodejs中创建单例eventemitter&;快速项目,javascript,node.js,express,eventemitter,Javascript,Node.js,Express,Eventemitter,我正在尝试为我的Nodejs/expressapi项目创建一个带有nodejseventemitters的发布者-订阅者模式。我的用例相当简单: 我希望从项目中的各个位置发出事件。例如,在创建新用户时发出事件 然后我想要一个单独的地方,在那里我倾听所有事件并决定采取什么行动 这将需要eventEmitter的单实例,因为“emit”和“on”调用应该发生在“event”对象的同一实例上 要实现这一点,我的index.js就是这样的: 这就是我的中间件/控制器函数的外观(我发出事件的地方): 这就

我正在尝试为我的Nodejs/expressapi项目创建一个带有nodejseventemitters的发布者-订阅者模式。我的用例相当简单:

  • 我希望从项目中的各个位置发出事件。例如,在创建新用户时发出事件
  • 然后我想要一个单独的地方,在那里我倾听所有事件并决定采取什么行动
  • 这将需要eventEmitter的单实例,因为“emit”和“on”调用应该发生在“event”对象的同一实例上

    要实现这一点,我的index.js就是这样的:

    这就是我的中间件/控制器函数的外观(我发出事件的地方):

    这就是我的事件订阅者文件的外观:

    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());
    
    而不是像这样

    app.use(eventListeners.eventSubscribers);
    
    app.use(eventListeners.eventSubscribers());
    
    如果我们比较上面两个表达式,在第二种情况下,当您调用时,express无法传递请求对象,但此函数调用不会向express返回任何内容,即有点无效,但在第一种情况下,由于您将函数对象引用传递给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模块 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;
    

    EventEmitter应按如下方式导入:
    const{EventEmitter}=require('events'));
    。事件模块有其他类和属性,现在您没有按预期导入它。当我进行此更改时,我的TypeError会消失,但当我从postman调用CreateUser API时,应用程序会挂起。它进入我的eventSubscriber内部,但不会出来。@VikalpJain是否确实使用了正确的EventEmitter是的,评论中提到了导入EventEmitter的另一种方法。或者,我认为您不需要使用中间件来使用EventEmitter,您可以只保留一个由EventEmitter组成的全局自定义实例作为它的属性,以及您要侦听的所有不同事件,然后在主条目文件中使用它们。您可以将EventEmitter用作此自定义模块的属性,通过在其中导入此自定义模块,可以在任何模块中发出事件。不,我不确定。事实上,我正试图实现您在评论中描述的内容,但无法对其进行结构设计。您能用一些代码解释吗?谢谢。@VikalpJain用working alte更新了答案非常感谢!这会让事情变得更清楚。我明天早上会试试,然后回来!