英文:
How do I trigger events from a handler so that another handler can listen to it in Express JS
问题
我正在构建一个Web应用程序,其中当有人发布帖子时,所有订阅者都会收到通知。我在Node.js中使用SSE(服务器发送事件)。我的示例代码如下。
postEvent.js
const EventEmitter = require("node:events");
class PostEvent extends EventEmitter {}
module.exports = new PostEvent();
post.js
const PostEvent = require('./postEvent');
app.post('/post', (req, res) => {
// 从req获取数据并保存到数据库
PostEvent.emit('posted');
})
sse.js
const PostEvent = require('./postEvent');
app.get('/sse', (req, res) => {
res.set('Content-Type', 'text/event-stream'); // 用于无限流式传输服务器响应
setInterval(() => res.write('data: 每秒的SSE数据\n\n'), 1000); // 这部分有效
PostEvent.on('posted', () => res.write('data: 已发布\n\n')); // 这部分无效
})
问题在于 PostEvent.on('posted', callback)
在我向 /post
路由发送fetch请求时不会运行。我是做错了什么还是事件系统不像这样工作?有什么其他方法可以实现这个功能吗?
注意: 未提到Express的样板代码,客户端部分在发送流时使用 EventSource
正常工作。
编辑: 我们是否可以在http或sse环境中使用此事件系统?我没有向/sse
发出请求,但我正在尝试在其中运行该函数。
英文:
I'm building a web app wherein when someone posts a post, all subscribers receive a notification. I'm using SSE (server sent events) in Node js. My example code looks like this.
postEvent.js
const EventEmitter = require("node:events");
class PostEvent extends EventEmitter {}
module.exports = new PostEvent();
post.js
const PostEvent = require('./postEvent');
app.post('/post', (req, res) => {
// get data from req and save to the database
PostEvent.emit('posted');
})
sse.js
const PostEvent = require('./postEvent');
app.get('/sse', (req, res) => {
res.set('Content-Type', 'text/event-stream'); // for streaming server response indefinitely
setInterval(() => res.write(`data: my sse data every second\n\n`), 1000); // this works
PostEvent.on('posted', () => res.write('data: posted\n\n')); // this doesn't
})
The problem here is that the PostEvent.on('posted', callback)
doesn't run when I send a fetch request to the /post
route. Am I doing something wrong or the event system doesn't work like this?
Is there anything else that I can do to implement this functionality?
Note: Express boilerplate code has not been mentioned and the client side functions properly with EventSource
when streams are sent.
Edit: Can we do this event system in an http or sse environment at all? I'm not making a request to /sse
, but I'm trying to run the function in it.
答案1
得分: 1
以下是您要翻译的内容:
"我无法在只使用一个文件来处理两个路由时重现您的问题:https://prnt.sc/sOzp0xHvpbDM
我猜测,当将它拆分为两个文件(post.js 和 sse.js)时,不同的 PostEvent 实例正在传递。如果是这种情况,那么您需要实例化然后在两个位置都传递相同的实例。
const express = require("express");
const PostEvent = require('./postEvent');
const app = express();
app.post('/post', (req, res) => {
PostEvent.emit('posted');
res.json("事件已发布");
})
app.get('/sse', (req, res) => {
res.set('Content-Type', 'text/event-stream');
setInterval(() => res.write(`data: 每秒我的 SSE 数据\n\n`), 1000);
PostEvent.on('posted', () => res.write(`data: 在 ${new Date().toLocaleTimeString()} 发布\n\n`));
})
const PORT = 3000;
app.listen(PORT, function (err) {
if (err) console.log(err);
console.log("服务器监听端口", PORT);
});
希望这对您有所帮助。
英文:
I was not able to reproduce your problem when using only one file for both routes: https://prnt.sc/sOzp0xHvpbDM
My bet is that when having it split in 2 files (post.js and sse.js) different instances of the PostEvent are being passed. If that is the case then you will need to instantiate and then pass the same in both spots.
const express = require("express");
const PostEvent = require('./postEvent');
const app = express();
app.post('/post', (req, res) => {
PostEvent.emit('posted');
res.json("event posted");
})
app.get('/sse', (req, res) => {
res.set('Content-Type', 'text/event-stream');
setInterval(() => res.write(`data: my sse data every second\n\n`), 1000);
PostEvent.on('posted', () => res.write(`data: posted in ${new Date().toLocaleTimeString()} \n\n`));
})
const PORT = 3000;
app.listen(PORT, function (err) {
if (err) console.log(err);
console.log("Server listening on PORT", PORT);
});
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论