背景
最近做类似AI会话gpt流式输出的效果,借助 vue 的数据响应,可轻松实现流式输出,在 vue3+vite 的架构中,可以实现流式输出,今天同样功能特定客户需要vue2 + webpack来实现,要我写个demo,代码逻辑迁移过去换个写法而已,简单。。 可是写完后发现无法流式输出,总是一下子全部返回数据,即使设置了流式返回。
请求代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| fetch(`/llmops/chat/apps/348/conversations/${this.currentChatParam.conversationId}/qas/${qaId}/stream`, { method: 'POST', headers: { 'Accept': 'text/event-stream', 'Content-Type': 'application/json', }, credentials: 'include', body: JSON.stringify({ chatLogId }) }) .then(response => { if (response.ok) { const reader = response.body.getReader(); const decoder = new TextDecoder('utf-8'); let buffer = ''; this.responseData = []; this.idx = 0;
const processStream = ({ done, value }) => { if (done) { console.log('getResAnswer-4', Date.now()); if (buffer) { const lines = buffer.split('\n').map(it => it.trim()).filter(it => it); lines.forEach(line => { const str = line.trim().split('data:')[1]; if (str) { const parsedData = JSON.parse(str); this.responseData.push({ answer: parsedData.answer, answerType: 'text', isEnd: parsedData.isEnd === 1, }); } }); } return; }
buffer += decoder.decode(value, { stream: true });
let lines = buffer.split('\n').map(it => it.trim()).filter(it => it); buffer = lines.pop();
lines.forEach((line, idx) => { const str = line.trim().split('data:')[1]; if (str) { const parsedData = JSON.parse(str); const isEnd = parsedData.isEnd === 1; this.responseData.push({ answer: parsedData.answer, answerType: 'text', isEnd, }); } });
return reader.read().then(processStream); };
reader.read().then(processStream); } else { console.error('Failed to connect to the stream:', response.status); } }) .catch(error => console.error('Fetch error:', error));
|
解决方法
webpack中 默认开启了 compress,在 vue.config.js 设置为false,
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| devServer: { host: "0.0.0.0", port: 5001, open: true, compress: false, proxy: { "/aaaaaa/": { target: "http://aaaaaaaaa/", changeOrigin: true, secure: false, }, }, },
|
此时可流式输出,vite中 compress 默认是 false 所以不用设置就可流式输出
nginx配置
1 2 3 4 5 6 7 8
| location / { add_header Cache-Control no-cache; proxy_set_header Connection ''; proxy_http_version 1.1; chunked_transfer_encoding off; proxy_buffering off; proxy_cache off; }
|
参数解释
在 vue.config.js
文件中,devServer
是一个用于配置 Vue CLI 项目开发服务器的对象。当你设置 compress: false
时,你实际上是在告诉开发服务器不要对响应的内容进行压缩。
compress 选项的作用通常是控制开发服务器是否应该使用 gzip 或其他压缩算法来压缩发送给浏览器的响应内容。当设置为 true
时,服务器会尝试压缩响应,这通常可以减少传输的数据量,因为压缩后的内容通常比原始内容更小。但是,这也需要额外的 CPU 时间来进行压缩和解压缩操作。
在开发环境中,compress: false
可能有以下好处:
- 更快的响应速度:由于不需要进行压缩和解压缩操作,服务器可以更快地发送响应给浏览器。
- 避免压缩相关的错误:有时,压缩算法可能会与某些内容类型或代码不兼容,导致在浏览器中出现显示问题或错误。在开发环境中禁用压缩可以避免这些问题。
- 简化调试:未压缩的响应内容更易于阅读和调试,特别是当你正在查看网络请求和响应时。
然而,在生产环境中,你通常会希望启用响应压缩(例如,通过设置 HTTP 头部 Content-Encoding: gzip
),以减少网络传输的开销和提高用户体验。这通常是在 Web 服务器(如 Nginx、Apache)或 CDN 层面上配置的,而不是在应用程序的开发服务器中。
总之,compress
选项在 vue.config.js
的 devServer
配置中用于控制开发服务器是否应该对响应内容进行压缩。将其设置为 false
可以加快开发过程中的响应速度,并避免与压缩相关的潜在问题。