如何实现像ChatGPT这样实现打字机效果(前端)

1,079 阅读2分钟

我的博客原文

@author: 郭瑞峰

@createTime: 2023/09/07

@updateTime: 2023/09/11

前言

相信很多小伙伴已经用过chatGPT模型了,不知道有没有小伙伴好奇chatGPT一个一个蹦出的回答是怎么实现的 (估计就只有我这个闲人才注意到这个并较真) (⊙x⊙;)

当然,老规矩,先把demo放上来,方便大佬们直接琢磨。 demo

way1: 基于 fetch 单向请求

对应在http://localhost:3303/fetch中,1秒后页面开始“一个一个蹦出来”,很神奇吧,接下来听我细细唠叨(哔哔赖赖)。

fetchbody.getReader方法可以以流的方式逐个读取响应数据块,当body.getReader().read().donetrue时,代表着数据传输完毕,可以结束当前请求。

如果你要看控制台的话,在“打字”状态下是看不见任何响应数据,只有等着请求完成后才能看见。

Weixin Screenshot_20230911103445.png

完成响应前

Weixin Screenshot_20230911103642.png

完成响应后

注意:这种单项请求只能用fetch完成,不能用XMLHttpRequest原因在于其responseText属性会在整个响应接收完毕后才返回完整的数据。

way2:基于 web-socket 双向消息推送

对应在http://localhost:3303/socket中,进入页面后会自动“蹦出来”,这个原理就很简单了,就是通过web-socket双向通信来进行,设置好传输类型,心跳频率就可以实现。

控制台network切换至ws就可以看见服务器端返回的消息。 Weixin Screenshot_20230911103837.png

way3:基于 SSE 服务器流式响应

简单说,它是基于http协议,让服务器能以数据流的方式传输给浏览器。(参考[1])

后端将响应头设置text/event-stream后就可以使用http协议传输数据流。不过请注意:

  • 后端传输流的时候需要按照这个数据类型传输,不然前端获取不了数据。
  • 若设计\n换行符,请用与前端协商用其他方式代替传输,如用\\n字符串代替。

参考[2]

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()
})

Weixin Screenshot_20230911110535.png

文献参考:

[1]《Server-Sent Events 教程》,阮一峰老师

[2]《ChatGPT 流式响应背后的技术》,A接拉起007老师

blob-Draft-1694352003157.png