最近需要对接一个AI大模型,后端使用SSE流式传输,要求前端实现打字机效果,即一个字一个字显示的效果,记录一下解决方法
tips:流式传输的数据是可以在浏览器开发者工具中的网络中看到的(会有一个EventSource选项卡)
首先的想法是使用浏览器原生的SSE接口,可以自动解析流式数据的事件名,数据等,但是EventSource构造函数不能接受header配置,如果token是放在header中的,就不能使用这个方式
查询资料发现fetch支持流式接收数据,示例:
const res=fetch("/api/chat");//直接使用
const reader = res.body.getReader();//获取ReadableStream
const decoder = new TextDecoder(); //将Uint8Array解码
let done = false;
let data = '';
while (!done) {
const { value, done: doneReading } = await reader.read();
done = doneReading;
if (value) {
data += decoder.decode(value, { stream: true });
}
}
注意,decode
时需要加上{ stream: true }
参数,因为流式传输时,一个汉字/emoji符号会被拆成多个码点,可能正好不在同一块数据中,stream: true
可以在下次解码时自动将缓存字节与新数据块开头拼接,保证正确解码
如果想使用axios,需要在axios.create
时使用adapter:"fetch"
,因为默认的xhr适配器不支持stream,然后在axios.post
时配置responseType: 'stream'
即可