AI初探--文字展示--SSE(Server Send Events)
SSE初探
SSE(Server-Sent Events)是一种服务器推送技术,允许服务器通过HTTP连接向客户端自动发送更新。它描述了服务器在建立初始客户端连接后如何向客户端发起数据传输。SSE通常用于向浏览器客户端发送消息更新或连续数据流,并通过名为EventSource的JavaScript API来增强原生、跨浏览器的流式传输。
SSE的历史: SSE机制最早由Ian Hickson在2004年的“WHATWG Web Applications 1.0”提案中指定。2006年9月,Opera浏览器在一个名为“Server-Sent Events”的实验性功能中实现了这项技术。
浏览器支持: 所有现代浏览器都支持Server-Sent Events:Firefox 6+、Google Chrome 6+、Opera 11.5+、Safari 5+、Microsoft Edge 79+。
SSE的优势:
- 简单易用:SSE使用标准的HTTP协议,无需特殊的协议或服务器实现即可工作。
- 单向通信:SSE提供了一种单向的服务器到客户端的通信方式,适用于那些只需要服务器向客户端发送更新的场景。
- 自动重连:当连接关闭时,浏览器会自动尝试重新连接服务器,无需手动处理连接问题。
- 事件标识:SSE支持给事件附加唯一的标识符,可以帮助浏览器在连接断开后确定应该触发哪个事件。
- 多行数据:SSE支持发送多行数据,可以方便地发送JSON等复杂数据格式。
SSE的用途: SSE适用于许多实时更新的场景,例如:
- 实时新闻更新
- 股票行情推送
- 地图上的位置跟踪
- 社交媒体的实时通知
- 在线聊天应用等
但我们这里想要聊的 SSE 的最核心的用途在于,AI聊天的推送,也就是为什么它可以一段一段的发送,而不用等全部结束再发送。
如何实现?
我们实现 SSE 可以通过 fetch 和 EventSource 的方式。
fetch 实现
我们先来聊聊 fetch 的实现
const endpoint = 'http://example.com/sse';
fetch(endpoint, {
headers: { 'Accept': 'text/event-stream' },
}).then(response => {
const reader = response.body.getReader();
let buffer = '';
reader.read().then(function process({ done, value }) {
if (done) {
console.log('Stream closed');
return;
}
buffer += new TextDecoder('utf-8').decode(value);
const lines = buffer.split('\n');
buffer = lines.pop();
lines.forEach(line => {
console.log(line);
});
// Continue reading
return reader.read().then(process);
});
}).catch(error => {
console.error(error);
});
fetch() 的优点:
-
更灵活的数据处理:使用 fetch() 方法可以更灵活地处理 SSE 数据流,因为我们可以使用 JavaScript 中的任何方法来处理和解析从 SSE 服务器端点接收的数据流。
-
更高的兼容性:fetch() 方法是一个标准的 Web API,支持所有主流的现代浏览器。
-
更好的控制权:使用 fetch() 方法可以更好地控制 SSE 数据流的读取和处理。我们可以手动控制 SSE 数据流的读取进度,而不是依赖于 EventSource 对象的自动控制。
fetch() 的缺点:
-
需要手动解析数据:使用 fetch() 方法需要手动解析从 SSE 服务器端点接收的数据流,这需要一些额外的代码和技术。
-
无法自动重连:使用 fetch() 方法无法自动重连 SSE 服务器端点。如果与 SSE 服务器端点的连接断开,我们需要手动重新连接。
-
无法处理错误:使用 fetch() 方法无法处理 SSE 数据流的错误。如果发生错误,我们需要手动处理并调试代码。
EventSource 的实现
const endpoint = 'http://example.com/sse';
const eventSource = new EventSource(endpoint);
eventSource.addEventListener('open', event => {
console.log('Connected to SSE server');
});
eventSource.addEventListener('message', event => {
console.log(event.data);
});
eventSource.addEventListener('error', error => {
console.error(error);
});
setTimeout(() => {
eventSource.close();
console.log('Connection closed');
}, 60000);
EventSource 的优点:
-
自动重连:EventSource 对象提供了自动重连的功能。如果与 SSE 服务器端点的连接断开,EventSource 对象会自动尝试重新连接,并恢复之前的数据流。
-
自动解析数据:EventSource 对象自动解析从 SSE 服务器端点接收的数据流,并将其转换为 JavaScript 对象,方便我们进行处理和操作。
-
错误处理:EventSource 对象提供了错误处理的功能。如果发生错误,EventSource 对象会触发错误事件,并提供错误信息,方便我们进行调试和处理。
EventSource 的缺点:
-
低兼容性:EventSource 对象是一个 HTML5 新增的 Web API,可能不被所有的浏览器所支持。一些旧版的浏览器可能不支持 EventSource 对象。
-
可能会出现内存泄漏:使用 EventSource 对象可能会出现内存泄漏的问题,特别是在长时间运行的情况下。因此,我们需要注意释放 EventSource 对象。
后话
我们既可以自己用原生的实现方式,还可以用别人封好的工具库,比如@rangermauve/fetch-event-source
。
SSE 本质上其实还是属于 HTTP 请求,只是通过添加了accept: 'text/event-stream',将传输过程转化成了“流”的形式。
那么这就是本篇文章的全部内容啦
转载自:https://juejin.cn/post/7304563142957006867