@author: 郭瑞峰
@createTime: 2023/09/07
@updateTime: 2023/09/11
前言
相信很多小伙伴已经用过chatGPT模型了,不知道有没有小伙伴好奇chatGPT一个一个蹦出的回答是怎么实现的
(估计就只有我这个闲人才注意到这个并较真)
(⊙x⊙;)
当然,老规矩,先把demo放上来,方便大佬们直接琢磨。
demo
way1: 基于 fetch 单向请求
对应在http://localhost:3303/fetch中,1秒后页面开始“一个一个蹦出来”,很神奇吧,接下来听我细细唠叨(哔哔赖赖)。
fetch的body.getReader方法可以以流的方式逐个读取响应数据块,当body.getReader().read().done为true时,代表着数据传输完毕,可以结束当前请求。
如果你要看控制台的话,在“打字”状态下是看不见任何响应数据,只有等着请求完成后才能看见。
注意:这种单项请求只能用fetch完成,不能用XMLHttpRequest原因在于其responseText属性会在整个响应接收完毕后才返回完整的数据。
way2:基于 web-socket 双向消息推送
对应在http://localhost:3303/socket中,进入页面后会自动“蹦出来”,这个原理就很简单了,就是通过web-socket双向通信来进行,设置好传输类型,心跳频率就可以实现。
控制台network切换至ws就可以看见服务器端返回的消息。
way3:基于 SSE 服务器流式响应
简单说,它是基于http协议,让服务器能以数据流的方式传输给浏览器。(参考[1])
后端将响应头设置text/event-stream后就可以使用http协议传输数据流。不过请注意:
- 后端传输流的时候需要按照这个数据类型传输,不然前端获取不了数据。
- 若设计
\n换行符,请用与前端协商用其他方式代替传输,如用\\n字符串代替。
const sendMsg = `event:${event}\ndata:${data}\n\n`
前端就需要EventSource来请求,代码如下:
const eventSource = new EventSource('目标地址')
eventSource.addEventListener('message', ({ data }) => {
console.log(data)
})
eventSource.addEventListener('error', () => {
console.log('连接异常')
eventSource.close()
})
eventSource.addEventListener('end', () => {
console.log('流式响应结束')
eventSource.close()
})
文献参考:
[1]《Server-Sent Events 教程》,阮一峰老师
[2]《ChatGPT 流式响应背后的技术》,A接拉起007老师