解决微信小程序真机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!

相关推荐
三七吃山漆7 小时前
攻防世界——wife_wife
前端·javascript·web安全·网络安全·ctf
用户47949283569157 小时前
面试官问"try-catch影响性能吗",我用数据打脸
前端·javascript·面试
GISer_Jing8 小时前
前端营销技术实战:数据+AI实战指南
前端·javascript·人工智能
GIS之路8 小时前
使用命令行工具 ogr2ogr 将 CSV 转换为 Shp 数据(二)
前端
嘉琪0018 小时前
Vue3+JS 高级前端面试题
开发语言·前端·javascript
vipbic9 小时前
用 Turborepo 打造 Strapi 插件开发的极速全栈体验
前端·javascript
天涯学馆9 小时前
为什么 JavaScript 可以单线程却能处理异步?
前端·javascript
Henry_Lau6179 小时前
主流IDE常用快捷键对照
前端·css·ide
陶甜也9 小时前
使用Blender进行现代建筑3D建模:前端开发者的跨界探索
前端·3d·blender
我命由我1234510 小时前
VSCode - Prettier 配置格式化的单行长度
开发语言·前端·ide·vscode·前端框架·编辑器·学习方法