如何实现后端向前端实时推送动态生成的数据?(含Fetch API示例)
实现后端实时推送数据到前端的方案
你的当前代码存在两个核心问题:
- 后端多次调用
res.send()不符合HTTP协议规范,一个HTTP请求只能对应一个响应,重复调用会直接触发报错。 - 前端使用的
fetch是单次HTTP请求,仅能接收一次响应结果,无法持续监听后端生成的新增数据。
下面提供两种主流的实时推送实现方案:
方案一:Server-Sent Events(SSE)
SSE是基于HTTP的单向推送技术,专门用于后端向前端实时发送数据,实现简单,完全匹配你“后端有数据就推给前端”的需求。
前端代码(替换原fetch逻辑)
// 创建SSE连接,指定后端接口 const eventSource = new EventSource('/api/blah'); // 监听后端推送的消息 eventSource.onmessage = function(event) { const data = JSON.parse(event.data); if (data.status === 'success') { console.log(data.numbers); } }; // 监听连接错误,避免无限重连 eventSource.onerror = function(error) { console.error('SSE连接出错:', error); eventSource.close(); };
后端代码(修改原distribution逻辑)
const distribution = (req, res) => { const request = JSON.parse(req.body.request); if (request.requestType === 'numbers') { // 设置SSE专属响应头,保持连接存活 res.writeHead(200, { 'Content-Type': 'text/event-stream', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive' }); let ceiling = 100; let floor = 1; let x = 1; let step = 1; const intervalId = setInterval(() => { // 以SSE格式发送数据,必须以\n\n结尾 res.write(`data: ${JSON.stringify({ status: 'success', numbers: x })}\n\n`); x += step; if (x === ceiling || x === floor) { step = -step; } }, 500); // 监听客户端断开连接,及时清除定时器释放资源 req.on('close', () => { clearInterval(intervalId); res.end(); }); } };
方案二:WebSocket
WebSocket是双向通信协议,支持前后端互相发送消息,如果后续需要前端给后端发送指令(比如暂停推送),这个方案更灵活。
前端代码
// 创建WebSocket连接(生产环境用wss协议) const socket = new WebSocket('ws://your-domain/api/blah'); // 连接成功后,发送请求类型 socket.onopen = function() { socket.send(JSON.stringify({ request: `{"requestType": "numbers"}` })); }; // 接收后端推送的数据 socket.onmessage = function(event) { const data = JSON.parse(event.data); if (data.status === 'success') { console.log(data.numbers); } }; // 监听错误与关闭事件 socket.onerror = function(error) { console.error('WebSocket连接出错:', error); }; socket.onclose = function(event) { console.log('WebSocket连接关闭:', event); };
后端代码(以Express为例,需安装ws库)
先安装依赖:npm install ws
const WebSocket = require('ws'); const wss = new WebSocket.Server({ port: 8080 }); // 可与Express共用端口,需额外配置 wss.on('connection', (ws) => { ws.on('message', (message) => { const request = JSON.parse(JSON.parse(message).request); if (request.requestType === 'numbers') { let ceiling = 100; let floor = 1; let x = 1; let step = 1; const intervalId = setInterval(() => { ws.send(JSON.stringify({ status: 'success', numbers: x })); x += step; if (x === ceiling || x === floor) { step = -step; } }, 500); // 客户端断开时清除定时器 ws.on('close', () => { clearInterval(intervalId); }); } }); });
内容的提问来源于stack exchange,提问作者seriously
相关产品推荐
相关产品推荐

