> 技术文档 > 解决微信小程序中调用流式接口,处理unicode编码时 TextDecoder 不兼容的问题_微信小程序 textdecoder

解决微信小程序中调用流式接口,处理unicode编码时 TextDecoder 不兼容的问题_微信小程序 textdecoder


问题复现

      最近在开发一个 AI 问答小程序时,由于接口返回的是流式unicode编码数据,因此我使用了 TextDecoder decode 方法将二进制数据转换为文本。在开发环境中,数据处理一直没有问题,但在真机测试及上线后,发现调用接口时出现了 TextDecoder is not defined 的报错,导致数据无法正常显示。最终发现,问题出在 TextDecoder 这个 Web API 在小程序的生产环境中并不兼容。

//unicode编码转字符串arrayBufferToString(buffer){ return new TextDecoder().decode(buffer);}

解决方案

一开始,我尝试了很多解决 TextDecoder 兼容性问题的库,例如 text-encoding、text-encoding-polyfill 和 buffer,但都没有完全解决问题。最后,我决定手写一个 TextDecoder 的实现,并将其挂载到全局。废话不多说,直接上代码,各位大哥直接复制粘贴即可。

// TextDecoder polyfillif (typeof TextDecoder === \'undefined\') { class TextDecoder { constructor(encoding = \'utf-8\') { this.encoding = encoding.toLowerCase(); } decode(dataView) { let data; if (dataView instanceof ArrayBuffer) { data = new Uint8Array(dataView); } else if (dataView instanceof Uint8Array) { data = dataView; } else { throw new Error(\'参数必须是 ArrayBuffer 或 Uint8Array\'); } if (this.encoding === \'utf-8\') { return this._decodeUTF8(data); } else { throw new Error(\'当前只支持 UTF-8 编码\'); } } _decodeUTF8(data) { let str = \'\'; let i = 0; while (i < data.length) { let byte1 = data[i]; let char; // ASCII 字符 if (byte1 < 0x80) { char = String.fromCharCode(byte1); i += 1; } // 2字节序列 else if (byte1 < 0xE0) { const byte2 = data[i + 1]; char = String.fromCharCode(((byte1 & 0x1F) << 6) | (byte2 & 0x3F)); i += 2; } // 3字节序列 else if (byte1 < 0xF0) { const byte2 = data[i + 1]; const byte3 = data[i + 2]; char = String.fromCharCode( ((byte1 & 0x0F) << 12) | ((byte2 & 0x3F) << 6) | (byte3 & 0x3F) ); i += 3; } // 4字节序列 else { const byte2 = data[i + 1]; const byte3 = data[i + 2]; const byte4 = data[i + 3]; let codepoint = ((byte1 & 0x07) << 18) | ((byte2 & 0x3F) << 12) | ((byte3 & 0x3F) <> 10) + 0xD800; const lowSurrogate = (codepoint & 0x3FF) + 0xDC00; char = String.fromCharCode(highSurrogate, lowSurrogate); i += 4; } str += char; } return str; } } // 全局注入 TextDecoder globalThis.TextDecoder = TextDecoder;}

新建一个 textDecoder.js 文件,将自定义的 TextDecoder 代码放入其中。然后在 app.js 中通过 import 进行导入。这样,我们的 TextDecoder 就可以在生产环境中正常使用了。

// app.jsconst request = require(\'./utils/request\')import \'./utils/textDecoder\'App({ onLaunch() { // 展示本地存储能力 const logs = wx.getStorageSync(\'logs\') || [] logs.unshift(Date.now()) wx.setStorageSync(\'logs\', logs) // 登录 request.login(); }, globalData: { userInfo: null }})