如何调试JavaScript中的EventSource?排查onerror触发问题
错误原因及排查修复方案
错误核心原因
后端SSE格式完全不符合规范
EventSource(Server-Sent Events)要求输出必须遵循严格的格式:每条消息必须以data:前缀开头,且以两个换行符\n\n结尾。你的PHP代码直接输出OpenAI返回的原始数据,还额外添加了<br><br>标签,完全破坏了SSE的格式规则,导致前端无法识别消息,直接触发onerror事件。前端未处理
[DONE]的边界错误
当收到[DONE]标记时,你仍会执行JSON.parse(e.data),但[DONE]不是合法JSON格式,会直接抛出语法错误,进而触发EventSource的错误事件。
排查&修复步骤
1. 后端修复(优先级最高)
修改PHP回调函数,严格按照SSE规范输出数据,移除多余的HTML标签:
$opts = [ 'prompt' => $_GET["q"], 'temperature' => 0.9, "max_tokens" => 150, "frequency_penalty" => 0, "presence_penalty" => 0.6, "stream" => true, ]; header('Content-type: text/event-stream'); header('Cache-Control: no-cache'); // 跨域场景需添加CORS头 header('Access-Control-Allow-Origin: *'); $open_ai->completion($opts, function ($curl_info, $data) { $trimmedData = trim($data); // 跳过空数据或[DONE]标记 if($trimmedData === '' || $trimmedData === '[DONE]'){ return strlen($data); } // 按照SSE格式输出 echo "data: {$trimmedData}\n\n"; ob_flush(); flush(); return strlen($data); });
注:如果你的OpenAI SDK返回的流式数据已经自带
data:前缀,直接输出原始$data即可,无需手动添加。
2. 前端修复
在onmessage中先判断[DONE]标记,避免无效的JSON解析,同时添加异常捕获:
var eventSource = new EventSource(base_url + 'files/chatgpt.php?q=' + encodeURIComponent($el.val())); var div = document.getElementById('divID'); eventSource.onmessage = function (e) { const data = e.data.trim(); if(data === "[DONE]"){ div.innerHTML += "<br><br>Hello"; eventSource.close(); // 完成后主动关闭连接 return; // 终止后续代码执行 } try { const parsedData = JSON.parse(data); div.innerHTML += parsedData.choices[0].text; } catch (err) { console.error('数据解析失败:', err); // 捕获解析错误,避免触发全局onerror } }; eventSource.onerror = function (e) { console.error('EventSource连接错误:', e); eventSource.close(); // 出错后关闭连接 };
注:用
encodeURIComponent处理查询参数,避免特殊字符导致URL失效。
3. 额外排查点
- 打开浏览器开发者工具的Network面板,查看请求的响应内容是否符合
data: 内容\n\n的SSE格式 - 检查PHP错误日志,确认后端是否有未捕获的异常或输出错误
- 跨域场景下,确保后端返回了正确的CORS响应头
内容的提问来源于stack exchange,提问作者Martin AJ
相关产品推荐
相关产品推荐

