解决微信小程序真机TextDecoder流式解析失败指南

1. 问题复现

在微信小程序开发时,使用sse接收接口返回的是流式编码数据是中文的非纯ASCII字符,需要使用TextDecoderdecode方法将二进制数据转换为文本。在开发环境中,数据处理一直没有问题,但在真机测试及上线后,发现调用接口时出现了TextDecoder is not defined的报错,导致数据无法正常显示。

线上报错,问题出在TextDecoderAPI在小程序的生产环境中并不兼容。

2 如何解决

sse接口返回可能是中文的ASCII编码,会出现这种问题,如果是非中文的纯ASCII编码则不会出现。下面我们说下两种问题的解决方式。

这两种处理方式的主要区别在于字符编码的处理方式以及对二进制数据的转换方法,它们在处理非ASCII字符(如中文)时会有差异。

2.1 中文编码

看网上需要引入额外的插件或者手写,其实并不需要,具体代码如下:

typescript 复制代码
const uint8Array = new Uint8Array(res.data);
const type = Object.prototype.toString.call(uint8Array);
if (type === "[object Uint8Array]") {
  txt = decodeURIComponent(escape(String.fromCharCode(...uint8Array)));
} else if (uint8Array instanceof ArrayBuffer) {
  const arr = new Uint8Array(uint8Array);
  txt = decodeURIComponent(escape(String.fromCharCode(...arr)));
}
  • 支持 UTF-8 编码​ ​:通过 escape + decodeURIComponent 组合,实现了​​UTF-8 字节序列到字符串的正确转换​ ​。escape 将多字节字符(如 UTF-8)转换为 %xx 格式的转义序列,decodeURIComponent 再将其解码为正确字符。

  • ​兼容性处理​ ​:检查输入数据类型(Uint8ArrayArrayBuffer),确保统一转换为 Uint8Array 后再处理。

    • 使用 Object.prototype.toString.call 是更安全的类型检查方式(避免原型被篡改时的误判)。
  • ​适用​​:能正确处理包含中文等非 ASCII 字符的流式数据(前提是原始数据是 UTF-8 编码)。

如果支持TextDecoder则使用下面代码:

ini 复制代码
// 使用 TextDecoder(需兼容性检查)
const decoder = new TextDecoder('utf-8');
txt = decoder.decode(uint8Array);

2.2 非中文编码

不含中文的编码,则直接使用如下代码:

ini 复制代码
const uint8Array = new Uint8Array(res.data);
let text = lastText + String.fromCharCode.apply(null, uint8Array);
  • ​直接转换​ :使用 String.fromCharCode.apply(null, uint8Array) 直接将每个字节转换为对应的 Unicode 字符。
  • ​仅适用于纯 ASCII 字符​ (0-127),因为 fromCharCode 按单字节处理,无法正确解析多字节编码(如 UTF-8 的中文字符)。

注意:如果 res.data 是 UTF-8 编码的流式数据(例如包含中文),这种方式会导致​​乱码​ ​,因为 UTF-8 的中文字符由多个字节组成,而 fromCharCode 会逐字节解析,破坏多字节序列。

2.3 为什么这种方式能正确处理中文?

  1. ​UTF-8 编码原理​​:

    • 中文字符在 UTF-8 中占 3~4 字节(如 "你" 的 UTF-8 编码是 0xE4 0xBD 0xA0)。
    • 直接 fromCharCode 会拆分成 3 个独立字符(乱码),而 escape 会将多字节序列转为 %E4%BD%A0,再通过 decodeURIComponent 还原为 "你"。
  2. escapedecodeURIComponent 的作用​​:

    javascript 复制代码
    // 示例:中文 "你" 的 UTF-8 编码 [0xE4, 0xBD, 0xA0]
    const bytes = new Uint8Array([0xE4, 0xBD, 0xA0]);
    
    // 第一步:String.fromCharCode 得到乱码 "ä½ "
    const raw = String.fromCharCode(...bytes); // "ä½ "
    
    // 第二步:escape 将乱码转为 "%E4%BD%A0"
    const escaped = escape(raw); // "%E4%BD%A0"
    
    // 第三步:decodeURIComponent 解码为正确字符 "你"
    const decoded = decodeURIComponent(escaped); // "你"

2.4 两者区别

特性 无中文 有中文
​字符编码支持​ 仅 ASCII UTF-8、ASCII 等
​中文处理​ 乱码 正常显示
​数据类型检查​ 严格检查 Uint8ArrayArrayBuffer
​实现复杂度​ 简单 较复杂(需组合编码函数)
​适用场景​ 纯英文文本或二进制数据 多语言文本(如中文、特殊符号)

3. 总结

最后总结一下:在微信小程序中,若返回的是中文的编码,真机TextDecoder 不可用,则使用替代方案。返回的是非中文的纯编码,则非常简单。

如有错误,请指正O^O!

相关推荐
码了三年又三年4 小时前
【方舟UI框架】Navigation
前端·arkui
@HNUSTer4 小时前
基于 HTML、CSS 和 JavaScript 的智能图像虚化系统
开发语言·前端·javascript·css·html
OEC小胖胖4 小时前
React学习之路永无止境:下一步,去向何方?
前端·javascript·学习·react.js·前端框架·react·web
啊啊啊啊8435 小时前
函数,数组与正则表达式
前端·chrome·正则表达式
YL有搞头7 小时前
VUE的模版渲染过程
前端·javascript·vue.js·面试·模版渲染
百思可瑞教育7 小时前
前端性能优化:请求和响应优化(HTTP缓存与CDN缓存)
前端·网络协议·http·缓存·性能优化·北京百思可瑞教育·百思可瑞教育
gnip11 小时前
文件操作利器:showOpenFilePicker
前端·javascript
繁依Fanyi12 小时前
做一个 3D 图片画廊
前端