React.js应用中EventSource on-message处理器未触发问题排查
解决React中EventSource onmessage不触发的问题
针对你遇到的React CRA环境下SSE连接正常但onmessage不执行的问题,结合旧jQuery客户端正常的情况,可按以下步骤排查解决:
1. 修复EventSource实例的作用域与生命周期问题
你当前在组件顶层直接创建EventSource实例,组件每次渲染都会重新生成新实例,导致useEffect中绑定的事件可能关联到已失效的实例上。改用useRef保存实例,确保整个组件生命周期内只有一个有效实例:
import { useRef, useEffect } from 'react'; // ...组件内部 const eventSourceRef = useRef(null); useEffect(() => { // 仅在实例不存在时创建 if (!eventSourceRef.current) { eventSourceRef.current = new EventSource("/api/register/39/event/944?registrationCode=MDB"); eventSourceRef.current.onopen = (e) => { console.log("DEBUG: eventSource connection open!", e); console.log(`DEBUG: onopen | readyState=${eventSourceRef.current.readyState}`); }; eventSourceRef.current.onerror = (e) => { if (eventSourceRef.current.readyState === EventSource.CLOSED) { console.log("DEBUG: eventSource connection CLOSED! Trying to reconnect!"); } }; eventSourceRef.current.onmessage = (event) => { console.log("DEBUG: onmessage received! result=", event.data); }; } // 组件卸载时关闭连接 return () => { if (eventSourceRef.current) { eventSourceRef.current.close(); eventSourceRef.current = null; } }; }, []); // 空依赖数组确保仅执行一次
2. 配置CRA代理以支持SSE流式响应
CRA默认代理可能未正确处理SSE的长连接与流式响应,需手动创建代理配置文件src/setupProxy.js:
const { createProxyMiddleware } = require('http-proxy-middleware'); module.exports = function(app) { app.use( '/api', createProxyMiddleware({ target: 'https://localhost:7001', changeOrigin: true, secure: false, // 本地自签HTTPS证书时需开启 onProxyReq: (proxyReq) => { // 保持长连接,避免代理自动添加Connection: close proxyReq.setHeader('Connection', 'keep-alive'); }, onProxyRes: (proxyRes) => { // 确保SSE响应头正确传递 proxyRes.headers['Cache-Control'] = 'no-cache'; proxyRes.headers['Content-Type'] = 'text/event-stream'; // 移除可能阻塞流式响应的头 delete proxyRes.headers['Content-Length']; } }) ); };
修改后需重启React开发服务生效。
3. 验证后端SSE响应格式是否严格符合规范
尽管旧客户端正常,不同客户端对SSE格式的容错性有差异。检查后端返回的每条消息必须符合:
- 以
data:开头 - 单条消息可跨行,每行都需
data:前缀 - 消息结尾必须是两个换行符(
\n\n)
示例正确格式:
data: {"type": "notice", "content": "test"} data: {"type": "alert", "content": "new message"}
可在浏览器Network面板中查看SSE请求的「Response」标签,确认格式是否合规。
4. 检查是否存在自定义事件类型
如果后端发送的是带event:字段的自定义事件(而非默认的message事件),onmessage不会触发,需监听对应事件名:
// 在useEffect中添加自定义事件监听 eventSourceRef.current.addEventListener('custom-event-name', (event) => { console.log("Custom event received:", event.data); });
可通过后端日志或Network响应内容确认是否存在event: xxx字段。
内容的提问来源于stack exchange,提问作者jn4
相关产品推荐
相关产品推荐

