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

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对话而言很重要,因为对话可能需要持续一段时间,连接的稳定性很重要。 - 简单性和易用性:相对于
WebSocket,EventSource的 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