微信小程序 request 流式数据处理

什么是流式数据处理?

流式数据处理(Streaming Data)指逐步接收并处理数据片段的技术,无需等待全部数据加载完成。适用于大文件下载、实时日志、AI生成报告等场景,可显著降低内存占用并提升用户体验。

微信小程序中的实现方案

微信小程序通过 wx.request 的 rsponseType:"arraybuffer" 返回二进制数据,enableChunked 配置启用分块传输,配合 onChunkReceived 回调实现流式处理。

通用方法封装

javascript 复制代码
/**
 * 流式请求封装
 * @param {string} url 请求地址
 * @param {Object} data 请求参数
 * @param {Function} onProgress 分块数据处理回调
 * @param {Object} headers 自定义请求头
 */
export function streamRequest({ url, data, onProgress, headers }) {
  return new Promise((resolve, reject) => {
    wx.request({
      url,
      data,
      header: headers || {},
      responseType: "arraybuffer", // 关键:接收二进制流
      enableChunked: true, // 启用分块传输
      success(res) {
        if (res.statusCode === 200) resolve(res);
      },
      fail(err) {
        reject(err)
      },
      onChunkReceived(response) {
        // 每次收到分块时触发
        const chunk = response.data; // 获取二进制数据块
        try {
          // 将ArrayBuffer转为可读字符串
          const textDecoder = new TextDecoder('utf-8');
          const chunkStr = textDecoder.decode(chunk); // data:{"done":false,"response":"异常"} data:{"done":false,"response":","} data:{"done":false,"response":"建议"} data:{"done":false,"response":"结合"}
          // 根据需要做后续处理
          onProgress?.(chunkStr);
        } catch (e) {
          console.error('Chunk parsing failed:', e);
        }
      }
    });
  });
}

使用示例:AI生成报告解读实时解析

html 复制代码
<template>
  <view class="page">
    <scroll-view
      class="ai-content"
      scroll-y
      style="max-height:calc(100vh - {{navHeight}}px);"
      enable-back-to-top
      scroll-top="{{scrollTop}}"
      bindscroll="scroll"
      :scroll-with-animation="false"
      bindscrolltolower="next"
    >
      <view bindtap="getAIReportDecode">开始生成</view>
      <view>
        <van-loading wx:if="{{loading}}"/>
        <view>
          <span>报告智能解读:</span>
          <rich-text nodes="{{result}}"></rich-text>
        </view>
      </view>
    </scroll-view>
  </view>
</template>
javascript 复制代码
<script>
import { Page } from "@wxa/core";
import { streamRequest } from "../../../../static/utils/index.js";

const MarkdownIt = require('markdown-it');
const md = new MarkdownIt();

var that, $data;

@Page
export default class Index {
  data = {
    result: "",
    loading: true,
    scrollTop: 0,
    isAutoScrolling: true, // 是否自动滚动
    word: "",
    targetScrollTop: 0,
    requestTask: null
  };

  async onLoad(e) {
    that = this;
    $data = that.data;
  }

  onUnload() {
    if ($data.requestTask) {
      $data.requestTask.abort();
    }
  }
  getAIReportDecode() {
    streamRequest({
      url: "https://api.example.com/ai/report",
      data: {},
      onProgress(res) {
        const messages = res.trim().split("\n\n");
        const parsedMessages = messages
          .map(message => {
            // 按 "data:" 拆分,取后面的部分
            const dataPart = message.split("data:")[1];
            if (dataPart) {
              // 解析 JSON 字符串并返回对象
              return JSON.parse(dataPart.trim());
            }
          })
          .filter(v => {
            return v;
          }); // 过滤掉异常值
        const line = parsedMessages.map(v => {
          return v.response;
        });
        line.forEach(v => {
          $data.word += line;
          that.setData({ result: md.render($data.word) });
          that.autoScrollToBottom();
        });
      }
    }).then(() => {
      console.log("报告接收完成");
    });
  }

  scroll(e) {
    if ($data.targetScrollTop > 0) {
      return; // 忽略此次滚动事件
    }
    const { scrollTop, scrollHeight } = e.detail;
    const query = wx.createSelectorQuery();
    query
      .select(".ai-content")
      .boundingClientRect(rect => {
        if (rect) {
          const clientHeight = rect.height;
          if (scrollTop + clientHeight < scrollHeight) {
            that.setData({ isAutoScrolling: false });
          }
        }
      })
      .exec();
  }

  next() {
    that.setData({
      targetScrollTop: 100
    });
    that.setData({ isAutoScrolling: true });
    setTimeout(() => {
      that.setData({
        targetScrollTop: 0 // 重置目标 scrollTop
      });
    }, 100);
  }

  autoScrollToBottom() {
    if (!$data.isAutoScrolling) return;

    const query = wx.createSelectorQuery();
    query
      .select(".ai-content")
      .boundingClientRect(rect => {
        that.setData({
          scrollTop: rect.height * 100,
          targetScrollTop: 100
        });
        setTimeout(() => {
          that.setData({
            targetScrollTop: 0 // 重置目标 scrollTop
          });
        }, 100);
      })
      .exec();
  }
}
</script>
javascript 复制代码
<config>
{
  "usingComponents": {
    "van-loading": "@vant/weapp/loading/index"
  }
}
</config>

Markdown 解析器安装:

bash 复制代码
yarn add markdown-it
相关推荐
拖孩13 小时前
用 AI 重解千年观音灵签,做了一个微信小程序,每天摇一摇,命运给你回应
前端·后端·微信小程序
黄华SJ520it15 小时前
顶俏洗衣液模式制度开发介绍:S2B2C社交分销+多门店核销系统全解析
前端·数据库·小程序·零售·系统开发
北极糊的狐18 小时前
钉钉小程序报错data.formatTime is not a function是因为 axml 模板中不能直接调用 Page 内自定义方法!
java·小程序·钉钉
java1234_小锋18 小时前
【免费】微信小程序网约车(打车,在线叫车,移动出行)系统(SpringBoot4+Vue3) 锋哥原创出品,必属精品
微信小程序·网约车·在线叫车·移动出行
show4332 天前
多格式导出怎么做?2026免费小程序TXT/SRT实践
开发语言·小程序·c#
AI砖家2 天前
AI编程—微信小程序开发规范
微信小程序·小程序·notepad++·ai编程
show4332 天前
2026小程序端视频转文字技术对比:识别引擎精度实测
小程序·音视频
sam-zy2 天前
微信小程序+ESP8266+Arduino 开发智能插座,有本地OTA功能
微信小程序·小程序
A24207349303 天前
微信小程序开发:常用基础语法与指令详解
微信小程序·小程序·notepad++
黄华SJ520it3 天前
青蓝送水类型社交裂变小程序系统技术拆解
小程序·系统开发