解决微信小程序中调用流式接口,处理二进制数据时 TextDecoder 不兼容的问题

news2025/3/12 9:32:55

问题复现

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

解决方案

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

// TextDecoder polyfill
if (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) << 6) |
            (byte4 & 0x3F);

          // UTF-16 surrogate pair
          codepoint -= 0x10000;
          const highSurrogate = (codepoint >> 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.js
const 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
  }
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2313679.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java 大视界 -- Java 大数据在智慧农业农产品质量追溯与品牌建设中的应用(124)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

c++介绍信号六

信号量是c中实现对有限资源访问控制&#xff0c;现成通过信号量获得对资源访问的许可。可用资源大于0&#xff0c;线程可以对资源进行访问&#xff0c;此时计数器减1。当计数器为0时&#xff0c;不可访问资源&#xff0c;线程进入等待。当资源释放时&#xff0c;线程结束等待&a…

GStreamer —— 2.18、Windows下Qt加载GStreamer库后运行 - “播放教程 6:音频可视化“(附:完整源码)

运行效果 介绍 GStreamer 带有一组将音频转换为视频的元素。他们 可用于科学可视化或为您的音乐增添趣味 player 的本教程展示了&#xff1a; • 如何启用音频可视化 • 如何选择可视化元素 启用音频可视化实际上非常简单。设置相应的标志&#xff0c;当纯音频流为 found&#…

用Deepseek写一个 HTML 和 JavaScript 实现一个简单的飞机游戏

大家好&#xff01;今天我将分享如何使用 HTML 和 JavaScript 编写一个简单的飞机游戏。这个游戏的核心功能包括&#xff1a;控制飞机移动、发射子弹、敌机生成、碰撞检测和得分统计。代码简洁易懂&#xff0c;适合初学者学习和实践。 游戏功能概述 玩家控制&#xff1a;使用键…

Android Compose MutableInteractionSource介绍

在 Android 开发中&#xff0c;Compose 是 Google 推出的现代化 UI 工具包&#xff0c;它让开发者能够更简洁高效地构建应用界面。而 MutableInteractionSource 是 Compose 中一个重要的组件&#xff0c;它可以帮助你处理用户与界面交互时的状态变化&#xff0c;尤其在处理交互…

[杂学笔记] TCP和UDP的区别,对http接口解释 , Cookie和Session的区别 ,http和https的区别 , 智能指针 ,断点续传

文章目录 1. TCP和UDP的区别2. 对http接口解释3. Cookie和Session的区别4. http和https的区别5. 智能指针6.断点续传 1. TCP和UDP的区别 tcp的特点&#xff1a; 面向连接&#xff0c;可靠性高&#xff0c;全双工&#xff0c;面向字节流udp特点&#xff1a;无连接&#xff0c;不…

【NLP 29、项目 Ⅰ:电商评论分类(好评 / 差评) 】

目录 项目介绍 一、训练及测试数据 二、代码实现 1.配置文件 config.py 2.分割训练集和验证集 split_train_valid.py 3.数据加载文件 loader.py Ⅰ、 加载和处理数据 DataGenerator ① 初始化 ② 数据加载 ③ 文本编码 ④ 补齐 / 截断 ⑤ 获取数据集长度和指定索引的数据 Ⅱ、加…

halcon deeplearn 语义分割经验分享 1

本人因为公司遗留问题,为了解决识别错误的问题。尝试过yolo12进行目标检测。初步测试良好但是是halcon的socket通信不行。故而去测试halcon 的deeplearn。自己标注数据。 注: 这个软件使用非常无脑。推荐没有基础的人去用 语义分割 以下是halcon的调用模型 *读取模型 read_dl_…

从零开始的python学习(五)P75+P76+P77+P78+P79+P80

本文章记录观看B站python教程学习笔记和实践感悟&#xff0c;视频链接&#xff1a;【花了2万多买的Python教程全套&#xff0c;现在分享给大家&#xff0c;入门到精通(Python全栈开发教程)】 https://www.bilibili.com/video/BV1wD4y1o7AS/?p6&share_sourcecopy_web&v…

Kylin麒麟操作系统服务部署 | ISCSI存储服务

以下所使用的环境为&#xff1a; 虚拟化软件&#xff1a;VMware Workstation 17 Pro 麒麟系统版本&#xff1a;Kylin-Server-V10-SP3-2403-Release-20240426-x86_64 一、网络存储结构 网络存储技术&#xff08;Network Storage Technologies&#xff09;是基于数据存储的一种通…

数据结构_单链表

今天我们要开启链表的学习 &#x1f58b;️&#x1f58b;️&#x1f58b;️ 学了顺序表我们可以知道&#xff1a; &#x1f388;链表其实就是争对顺序表的缺点来设计的&#xff0c;补足的就是顺序表的缺点 &#x1f388;链表在物理上是上一个节点存放的下一个节点的地址 链表 …

深陷帕金森困境,怎样重燃生活信心?

帕金森&#xff0c;这个悄然影响无数中老年人生活的神经系统疾病&#xff0c;正逐渐走进大众视野。患病后&#xff0c;患者常出现静止性震颤&#xff0c;安静时手部、下肢不自主抖动&#xff0c;如同在默默诉说着身体的异常。肢体变得僵硬&#xff0c;行动迟缓&#xff0c;起步…

C语言(23)

字符串函数 11.strstr函数 1.1函数介绍&#xff1a; 头文件&#xff1a;string.h char *strstr ( const char * str1,const char *str2); 作用&#xff1a;在一个字符串&#xff08;str1&#xff09;中寻找另外一个字符串&#xff08;str2&#xff09;是否出现过 如果找到…

Docker运行hello-world镜像失败或超时:Unable to find image ‘hello-world:latest‘ locally Trying to pull reposi

Docker运行hello-world镜像失败或超时&#xff0c;报错&#xff1a;Unable to find image ‘hello-world:latest’ locally Trying to pull repository docker.io/library/hello-world … /usr/bin/docker-current: missing signature key. See ‘/usr/bin/docker-current run …

Linux内核如何和设备树协同工作的?

1.编写设备树 cd arch/riscv/boot/dts/ 再cd到厂商&#xff0c;例如下述内容。 2.编译设备树&#xff08;dts->dtb&#xff09;通过dtc命令来转换 3.解析设备树 例如上述内容&#xff0c;都是对设备树的解析。 这里重点说一下内核对设备树的处理吧&#xff0c;因为这个内…

LLM中的transformer结构学习(二 完结 Multi-Head Attention、Encoder、Decoder)

文章目录 LLM中的transformer结构学习&#xff08;二 完结 Multi-Head Attention、Encoder、Decoder&#xff09;Self-Attention &#xff08;自注意力机制&#xff09;结构多头注意力 EncoderAdd & Norm 层Feed Forward 层 EncoderDecoder的第一个Multi-Head AttentionMas…

高效编程指南:PyCharm与DeepSeek的完美结合

DeepSeek接入Pycharm 前几天DeepSeek的充值窗口又悄悄的开放了&#xff0c;这也就意味着我们又可以丝滑的使用DeepSeek的API进行各种辅助性工作了。本文我们来聊聊如何在代码编辑器中使用DeepSeek自动生成代码。 注&#xff1a;本文适用于所有的JetBrains开发工具&#xff0c…

爱可以传递,幸福可以具象化

遇到什么&#xff1a;晚上上课学生吵吵吵&#xff0c;把学生手机全部收了&#xff0c;放讲台上。 感受到的情绪&#xff1a;很烦躁。 反思&#xff1a;收手机也不是长久之计&#xff0c;可是物理有什么翻转课堂呢&#xff1f; 明天的待办事项&#xff1a;早上高数选修课&#x…

力扣-数组-367 有效的完全平方数

思路和时间复杂度 思路&#xff1a;利用二分&#xff0c;确定区间是左闭右闭&#xff0c;然后根据大小进行二分时间复杂度&#xff1a; 代码 class Solution { public:bool isPerfectSquare(int num) {bool flag false;if(num 0 || num 1) return true;long long …

Java关键字与标识符

Java关键字是预定义的保留字&#xff0c;用于定义程序结构和语义&#xff0c;如if、for、class等&#xff0c;不能用作标识符。JDK 8有50个关键字&#xff0c;JDK 11引入var用于局部变量类型推断。标识符用于命名变量、类等&#xff0c;由字母、数字、_、$组成&#xff0c;不能…