You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让浏览器渲染EventSource流式返回内容中的HTML标签而非纯文本?

解决流式EventSource返回HTML标签无法渲染的问题

核心问题并非text/event-stream的响应类型导致浏览器无法解析HTML,而是流式传输过程中需要正确处理内容拼接与DOM插入逻辑,同时兼顾中间片段可能存在的未闭合标签。以下是两种可行方案:

方案1:缓存完整内容后一次性渲染

既然你确认流结束后整体内容完整,这种方法最简单,还能避免中间未闭合标签引发的渲染异常。

// 缓存流式返回的完整内容
let fullContent = '';
const msgContainer = document.querySelector('.msger-chat');

const evtSource = new EventSource('event-stream.php');

evtSource.onmessage = function(e) {
  try {
    const data = JSON.parse(e.data);
    const deltaContent = data.choices[0].delta.content;
    if (deltaContent) {
      fullContent += deltaContent;
    }
  } catch (err) {
    console.error('解析流式数据失败:', err);
  }
};

// 监听流结束事件(根据后端实现,也可使用evtSource.onclose)
evtSource.addEventListener('close', function() {
  // 处理换行并插入完整内容
  const formattedContent = fullContent.replace(/(?:\r\n|\r|\n)/g, '<br>');
  msgContainer.insertAdjacentHTML('beforeend', `<div class="msg ai-msg">${formattedContent}</div>`);
  evtSource.close();
});

evtSource.onerror = function(err) {
  console.error('EventSource连接异常:', err);
  evtSource.close();
};

方案2:实时渲染并处理未闭合标签

如果需要实时展示内容更新,可通过临时DOM元素让浏览器自动补全未闭合标签,保证每次渲染的都是合法HTML:

const msgContainer = document.querySelector('.msger-chat');
// 创建消息容器和临时处理节点
const msgDiv = document.createElement('div');
msgDiv.className = 'msg ai-msg';
const tempRenderDiv = document.createElement('div');
msgDiv.appendChild(tempRenderDiv);
msgContainer.appendChild(msgDiv);

const evtSource = new EventSource('event-stream.php');

evtSource.onmessage = function(e) {
  try {
    const data = JSON.parse(e.data);
    const deltaContent = data.choices[0].delta.content;
    if (deltaContent) {
      const formattedDelta = deltaContent.replace(/(?:\r\n|\r|\n)/g, '<br>');
      // 追加片段后,重新赋值innerHTML让浏览器自动补全标签
      tempRenderDiv.innerHTML += formattedDelta;
      tempRenderDiv.innerHTML = tempRenderDiv.innerHTML;
    }
  } catch (err) {
    console.error('解析流式数据失败:', err);
  }
};

evtSource.addEventListener('close', function() {
  evtSource.close();
});

关键注意事项

  • text/event-stream仅定义响应的传输格式,不会影响DOM对HTML内容的解析,只要使用innerHTML或insertAdjacentHTML插入内容,浏览器就会自动解析HTML标签。
  • 实时渲染时,浏览器自动补全的未闭合标签可能导致中间状态与最终内容有差异,但流结束后完整内容会自动修正显示效果。
  • 若返回内容不可信,需先进行XSS转义处理;若为可信后端内容,可直接使用上述逻辑。

内容的提问来源于stack exchange,提问作者sdavRaj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 05:17:28