【node-express-sse】Server Sent Event 单向推送消息,实现站内信功能
2024-01-02 19:00:13
实现效果
服务端返回的 Content-Type 是 text/event-stream,这是一个流,可以多次返回内容。
Sever Sent Event 就是通过这种消息来随时推送数据。
AIGC,如 ChatGPT 打字机消息回复实现原理 等也是使用sse实现。
还有站内信,或者一些日志推送,相较于繁重的 WebSockets,SSE 无疑是 H5 简单即时数据更新的轻量级代替方案。
源码:https://github.com/thinkasany/nestjs-course-code/tree/master/sse
代码
前端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React App</title>
</head>
<body>
<div id="root"></div>
<script crossorigin src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<script type="text/babel">
function App() {
const [messages, setMessages] = React.useState([]);
React.useEffect(() => {
const eventSource = new EventSource('http://localhost:3001/stream');
eventSource.onmessage = ({ data }) => {
const newData = JSON.parse(data).msg.split('\n').filter(str => str.trim() !== '');
// console.log('New message', newData);
setMessages(newData);
};
return () => {
eventSource.close();
};
}, []);
return (
<div>
<ul>
{messages.map((message, index) => (
<li key={index}>{message}</li>
))}
</ul>
</div>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
</script>
</body>
</html>
后端
const { exec } = require("child_process");
const { Observable } = require("rxjs");
const getLogChange = async (req, res) => {
const childProcess = exec("tail -f ./log");
res.setHeader("Content-Type", "text/event-stream");
res.setHeader("Cache-Control", "no-cache");
res.setHeader("Connection", "keep-alive");
const observer = msg => {
res.write(`data: ${JSON.stringify({ msg: msg.toString() })}\n\n`);
};
const observable = new Observable(obs => {
childProcess.stdout.on("data", msg => {
obs.next(msg);
});
});
const subscription = observable.subscribe(observer);
// 当连接断开时,停止子进程和 Observable
req.on("close", () => {
childProcess.kill();
subscription.unsubscribe();
});
};
module.exports = {
getLogChange
};
文章来源:https://blog.csdn.net/daddykei/article/details/135345242
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!