uniapp 微信小程序,最简单的流式输出:Transfer-Encoding: chunked

在GPT项目中,流式输出是实现流畅对话体验的关键技术之一。今天,我们将探讨如何在uniapp开发的微信小程序中优雅地实现这一功能。虽然WebSocket是一种常见的解决方案,但在某些场景下,我们可能寻求更轻量级且易于集成的替代方案。本文将介绍一种基于Transfer-Encoding: chunked的HTTP请求方式,它不仅避免了WebSocket的复杂性,同时也绕过了微信小程序对XHR和EventSource的限制。

在微信小程序环境下,由于平台限制,XHR和EventSource并不总是可用,而WebSocket的部署和维护成本相对较高。因此,我们探索了一种更为直接的方法------利用HTTP协议中的Transfer-Encoding: chunked特性。

实现细节:Transfer-Encoding: chunked
Transfer-Encoding: chunked允许服务器以分块的方式发送数据,而无需事先知道整个响应的大小。这种方式特别适合于流式输出场景,因为它可以实时地将数据推送给客户端,而无需等待整个响应构建完成。对于uniapp小程序而言,这意味着可以即时更新UI,提供更流畅的用户体验。

后台不需要改动,继续采用流式输出的形式即可,以通义千问的demo为例,代码如下

复制代码
@RequestMapping(value = "/completions", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<Result<CompletionsOutMsg>> completions(@RequestBody CompletionsInMsg inMsg) {
    ....
}

客户端处理:uniapp小程序

在uniapp小程序端,需要监听网络请求的onProgressUpdate事件或使用onChunkReceived回调来处理分块数据。下面是一个处理分块数据的示例代码:

复制代码
<template>
  <view class="page">
    <view class="box">
      <textarea class="uni-textarea" v-model="inputValue" placeholder="请输入内容"/>
    </view>
    <button class="mini-btn btn" type="primary" size="mini" @click="commit">提交</button>
    <view>
      {{ resultText }}
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      inputValue: '',
      resultText: '',
    };
  },
  methods: {
    commit() {
      var that = this;
      const requestTask = uni.request({
        url: 'YOUR_API_URL',
        method: 'POST',
        responseType: 'text',
        enableChunked: true,  //流式输出需要设置enableChunked为true
        data: {
          prompt: this.inputValue,
        },
        success: function (res) {
          console.log(JSON.stringify(res))
        },
        fail: function (err) {
        }
      });

      // 监听流式输出
      requestTask.onChunkReceived(function(res) {
        const uint8Array = new Uint8Array(res.data);
        let text = String.fromCharCode.apply(null, uint8Array);
        text = decodeURIComponent(escape(text));
        console.log(text);
        if (text) {
          let cleanedContent = text.replaceAll("data:", ',');
          let splitContent = "[" + cleanedContent.replace(/^,/, '') + "]";
          const dataArray = JSON.parse(splitContent);
          for (let i = 0; i < dataArray.length; i++) {
            that.resultText += dataArray[i].data.text;
          }
        }

      })


    },

  },


}
</script>

<style lang="scss">
.page {
  display: flex;
  justify-content: center;
  align-content: center;
  flex-direction: column;
}

.box {
  padding: 20rpx;
}

.btn {
  text-align: center;
  margin-top: 20rpx;
}

.uni-textarea {
  border: solid 1px #a59d9d;
  padding: 20rpx;
  width: 100%;
}

</style>
相关推荐
AI多Agent协作实战派13 小时前
AI多Agent协作系统实战(二十八):顶栏统一战争——从1个页面异常到31个页面全量对齐
数据库·人工智能·uni-app
00后程序员张14 小时前
iOS加固技术路线全面解析:Bitcode模式、源码模式与汇编模式对比及爱加密优势
android·汇编·ios·小程序·uni-app·cocoa·iphone
海纳百川·纳海川14 小时前
租房行业数字化:换个思路解决“老问题”
大数据·微信小程序·小程序
上海云盾-小余1 天前
CC 高频请求 + DDoS 流量攻击实战防御:全链路 WAF 流量清洗部署完整流程
网络·爬虫·安全·小程序·ddos
2501_916008891 天前
iOS IPA文件反编译与打包操作方法,拆包分析防护和加固打包
android·macos·ios·小程序·uni-app·cocoa·iphone
2301_810313181 天前
海外教育APP定制发展现状与开发选型核心要点解析
小程序·团队开发·软件需求
name好难取诶1 天前
通过对云基座和离线基座的对比,帮助开发者理解如何在不同场景下选择合适的打包方案。 什么是“基座” 在 UniApp 中,基座(也称“ ...
开发语言·uni-app·php
2501_915921431 天前
iOS手游安全反外挂解决方案:基于Xcode的加固混淆特色详解
android·安全·ios·小程序·uni-app·iphone·xcode
禾高网络2 天前
回收小程序在环保和商业领域发挥更大的作用
java·大数据·人工智能·小程序
2501_916007472 天前
iOS App分发教程 App Store、TestFlight 与 Ad Hoc 的配置与上传方法
android·ios·小程序·https·uni-app·iphone·webview