在 Node Js 和 Express 项目中创建单例 EventEmitter
Creating a Singleton EventEmittor in Nodejs & Express Project
我正在尝试使用 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
}
这就是我的 middleware/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 文件中有错误。我的问题:
- 这是创建 publisher/subscriber 模式的正确方法吗?
- 如何访问我的事件订阅者中的 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 组成的全局自定义实例,因为它是 属性 以及您想要收听的所有不同事件,然后在任何你需要的地方使用它们 them.You 可以使用 EventEmitter 作为这个自定义的 属性 通过导入这个自定义模块在你想要的任何模块中发出事件。
这是下面的工作示例
index.js file/entry 文件
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;
我正在尝试使用 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
}
这就是我的 middleware/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 文件中有错误。我的问题:
- 这是创建 publisher/subscriber 模式的正确方法吗?
- 如何访问我的事件订阅者中的 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 组成的全局自定义实例,因为它是 属性 以及您想要收听的所有不同事件,然后在任何你需要的地方使用它们 them.You 可以使用 EventEmitter 作为这个自定义的 属性 通过导入这个自定义模块在你想要的任何模块中发出事件。
这是下面的工作示例
index.js file/entry 文件
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;