Skip to content
标签
note
字数
1034 字
阅读时间
5 分钟

image.png

EventSource - Web API 接口参考 | MDN

EventSource 接口是 web 内容与服务器发送事件一个 EventSource 实例会对 HTTP 服务器开启一个持久化的连接,以 text/event-stream 格式发送事件,此连接会一直保持开启直到通过调用 EventSource.close() 关闭

EventSource

  • 优势:
    • 简单易用:EventSource API 非常简单,易于使用和理解。
    • 服务器推送:EventSource 适用于服务器主动向客户端推送数据,客户端只能接收服务器发送的事件。
    • 自动重连:EventSource 会自动处理连接断开和重新连接的情况,适用于长期保持连接并接收事件流的场景。
    • 兼容性:EventSource 在大多数现代浏览器中得到支持。
  • 劣势:
    • 单向通信:EventSource 只支持从服务器到客户端的单向通信,客户端无法向服务器发送数据。
    • 较少的功能:相比于 WebSocket,EventSource 提供的功能较为有限,仅限于接收服务器发送的事件。

WebSocket

  • 优势:
    • 双向通信:WebSocket 支持双向通信,客户端和服务器可以彼此发送数据。
    • 实时性:WebSocket 提供了更低的延迟和更快的数据传输速度,适用于实时性要求较高的应用场景。
    • 丰富的功能:WebSocket 提供了更多的功能,例如数据帧的自定义和二进制数据的传输等。
  • 劣势:
    • 复杂性:WebSocket API 相对于 EventSource 更为复杂,使用起来可能需要更多的代码和理解。
    • 需要服务器支持:使用 WebSocket 需要服务器端实现对应的 WebSocket 协议,而 EventSource 只需要服务器端支持发送事件即可。
    • 兼容性:相对于 EventSource,WebSocket 在某些较旧的浏览器或网络环境中的支持可能不够广泛。

为什么不用

  • 服务器推送:EventSource 专注于服务器向客户端主动推送事件的模型,这对于 ChatGPT 对话非常适用。ChatGPT 通常是作为一个长期运行的服务,当有新的回复可用时,服务器可以主动推送给客户端,而不需要客户端频繁发送请求。
  • 自动重连和错误处理:EventSource 具有内置的自动重连机制,它会自动处理连接断开和重新连接的情况。这对于 ChatGPT 对话而言很重要,因为对话可能需要持续一段时间,连接的稳定性很重要。
  • 简单性和易用性:相对于 WebSocketEventSource 的 API 更加简单易用,只需实例化一个 EventSource 对象,并处理服务器发送的事件即可。这使得开发者可以更快速地实现对话功能,减少了一些复杂性。
  • 广泛的浏览器支持:EventSource 在大多数现代浏览器中得到广泛支持,包括移动端浏览器。相比之下,WebSocket 在某些旧版本的浏览器中可能不被完全支持,需要考虑兼容性问题

SSE - Server-Sent Events

前端

js
const response = await fetch('http://127.0.0.1:7345/api/gpt/get', {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      message: message.value,
      role: role.value,
    }),
  });

  if (!response.body) return;
  const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
  while (true) {
    var { value, done } = await reader.read();
    if (done) break;
    value = value?.replace('undefined', '')
    console.log("received data -", value)
    output.value += value?.replace('undefined', '')
  }

后端服务

js
// 请求 GPT 服务
async function createChatCompletion(messages) {
  // 如下为 流式数据传输 写法
  const res = openai.createChatCompletion(
    {
      model: "gpt-3.5-turbo",
      messages,
      stream: true,
    },
    {
      responseType: "stream",
    }
  );
  return res
}

// 后端配置响应数据
res.setHeader("Cache-Control", "no-cache");
res.setHeader("Content-Type", "text/event-stream");
res.setHeader("Connection", "keep-alive");
res.flushHeaders();
const response = handlerFunction(req.body, req, res);
response.then((resp) => {
  resp.data.on("data", (data) => {
    console.log("stream data -", data.toString());
    const lines = data
      .toString()
      .split("\n\n")
      .filter((line) => line.trim() !== "");
    for (const line of lines) {
      const message = line.replace("data: ", "");
      if (message === "[DONE]") {
        res.end();
        return;
      }
      const parsed = JSON.parse(message);
      console.log("parsed content -", parsed.choices[0].delta.content);
      res.write(`${parsed.choices[0].delta.content}`);
    }
  });
});

参考

如何丝滑实现 ChatGPT 打字机流式回复?Server-Sent Events

贡献者

The avatar of contributor named as jiechen jiechen

页面历史

撰写