一.实现逻辑
1.使用 wx.request 开启流式输出(当然后端 也要开启 transfer-encoding: chunked)有些后端会默认开启
this.requestTask = wx.request({ url: \'xxxxxx\', enableChunked: true, //开启 transfer-encoding chunked。 method: \'POST\', header: { \'content-type\': \'application/json\', Authorization: `Bearer ${this.data.token}` }, data: { question: message } })
2.使用 onChunkReceived 来监听返回的数据
this.requestTask.onChunkReceived((res) => { console.log(res.data, 888) const parsed = this.decodeUint8Array(res.data) const temp = this.extractContentFromStream(parsed) console.log(temp)//转换之后的内容 })
3.处理sse返回的数据(默认返回的是 ArrayBuffer(87) {} )
import encoding from \'../../utils/encoding.js\' decodeUint8Array(uint8Array) { const data16 = this.buf2hex(uint8Array) const requestData = this.hexToStr(data16) return requestData }, buf2hex(arrayBuffer) { return Array.prototype.map.call(new Uint8Array(arrayBuffer), (x) => (\'00\' + x.toString(16)).slice(-2)).join(\'\') }, hexToStr(hex) { let trimedStr = hex.trim() let rawStr = trimedStr.substr(0, 2).toLowerCase() === \'0x\' ? trimedStr.substr(2) : trimedStr let len = rawStr.length if (len % 2 !== 0) { return \'\' } let curCharCode let resultStr = [] for (let i = 0; i < len; i = i + 2) { curCharCode = parseInt(rawStr.substr(i, 2), 16) resultStr.push(curCharCode) } let bytesView = new Uint8Array(resultStr) let str = new encoding.TextDecoder().decode(bytesView) return str }
4.需要两个文件 encoding.js 和 encoding-indexes.js 文件
二、问题
1.微信开发者工具中的 真机调试没反应(测试机 微信版本8.0.60)
使用微信开发者工具的 预览 或者 上传体验版本 测试
2.在微信开发者工具中 即使你开启了 enableChunked: true, 数据也不是 流式返回,而是只响应了一次,一次性返回的
升级最新版本的 微信开发者工具(我是这个原因,微信开发者工具太旧)
3.这时会遇到一个新的问题:微信开发者工具是 流式返回 但是真机测试又是一次性返回。。。。当时我真是吐血 ,看了微信开放社区 和 百度 ai 都没解决方法,最后发现是 后端 Nginx 配置问题
location /products/ai/ { proxy_pass http://localhost:5000; proxy_http_version 1.1; proxy_set_header Connection \"\"; proxy_buffering off; chunked_transfer_encoding on; proxy_hide_header Content-Length; }
后端在 nginx 加入之后 真机也能 流式返回
4.为什么会这样呢
因为后端使用的是 宝塔 ,默认会将 chunked 流式响应缓存/合并,有时即使后端返回 chunked
,前端收到的却是带 Content-Length
的完整包,即是 一次性的返回数据,也就是说被 nginx 缓冲了流式输出,最终一次性返回。 上诉配置 就是 禁用缓存