前言

最近写一个chagpt小程序,流式输出可以使用websocket也可以使用stream来实现,这里就不折腾websocket的了,我发现uniapp实现流式输出的方式挺多的,主要是有些小程序还不兼容,花了点时间研究了一下。

EventSource

EventSource也称为SSE(Server-Sent Events),是服务器推送的一个网络事件接口,一个EventSource会对http服务开启一个持久化链接,它发送的事件格式是‘text/stream’,开启EventSource事件后,它会一直保持开启状态,直到被要求关闭

SpringBoot实现SSE

@GetMapping("/sse")
public SseEmitter handleSse() {
SseEmitter emitter = new SseEmitter();
String data = "testStream";
try {
emitter.send(SseEmitter.event()
.id("[DATA]")
.data("hello")
.reconnectTime(3000));
emitter.send(SseEmitter.event()
.id("[DATA]")
.data("你好,世界。")
.reconnectTime(3000));
emitter.send(SseEmitter.event()
.id("[DONE]")
.data("done")
.reconnectTime(3000));
emitter.send("啊啊啊");
} catch (IOException e) {
emitter.completeWithError(e);
} emitter.complete();
return emitter;
}

XHR方式

uniapp自带的uni.request()不支持stream方式,所以可以使用XHR来实现,但是小程序又不支持XHR

const requestChat = (msg)=>{
// 在页面中创建 XMLHttpRequest 对象
var xhr = new XMLHttpRequest()
// 设置 XMLHttpRequest 对象
xhr.open('GET', 'http://localhost:8090/chat?msg=' + msg)
xhr.responseType = 'text'
xhr.timeout = 0
const msgNum = messageList.value.length;
xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.LOADING) {
// 处理 HTTP 数据块
console.log(xhr.responseText)
}
}
xhr.send()
}

EventSource方式

uniapp中也可以直接使用EventSource来实现流式输出,可惜小程序也不支持(难顶)

const chatStream = () => {
const es = new EventSource("http://localhost:8090/sse")
es.onmessage = function(event) {
console.log(event)
if (event.lastEventId=="[DONE]") {
console.log(event.data);
return es.close()
}
console.log(event.data);
};
}

Transfer-Encoding Chunk

uniapp中使用uni.request(),配置enableChunked: true即可

const requestTask = uni.request({
url: 'http://localhost:8090/sse',
timeout: 15000,
responseType: 'text',
method: 'GET',
enableChunked: true, //配置这里
data: {},
success: response => {
console.log(response)
},
fail: error => {}
})
requestTask.onHeadersReceived(function(res) {
console.log(res.header);
});
// 这里监听消息
requestTask.onChunkReceived(function(res) {
let decoder = new TextDecoder('utf-8');
let text = decoder.decode(new Uint8Array(res.data));
console.log(text)
})

由于接收到的数据是arraybuffer,所以我们要转换为字符串类型,但是编码会出现一点问题,上面这段代码使用TextDecoder来转换编码,但是小程序又不支持TextDecoder。。。

再换一种转换方式

requestTask.onChunkReceived(function(res) {
const uint8Array = new Uint8Array(res.data);
let text = String.fromCharCode.apply(null, uint8Array);
text = decodeURIComponent(escape(text));
console.log(text);
})

这样就可以在小程序中把Arraybuffer转换为字符串了

还有许多方式,比如调用第三方库来代替TextDecoder,我就不去尝试了

注意:

1.enableChunked: true流式响应开关,会自动在header中加入transfer-encoding chunked

2.arraybuffer转字符串问题,有TextDecoder就很好处理,没有也可以参照我上面的示例。

参考文章:

小程序如何实现类似ChatGPT的流式传输

微信小程序除了WebSocket其他思路实现流传输文字(打字机)效果

微信小程序ChatGpt流式响应

在微信小程序中如何支持使用流模式(stream),打造ChatGPT实时回复机器人,最详细讲解。

Uniapp仿ChatGPT Stream流式输出(非Websocket)的更多相关文章

  1. java1.8新特性之stream流式算法

    在Java1.8之前还没有stream流式算法的时候,我们要是在一个放有多个User对象的list集合中,将每个User对象的主键ID取出,组合成一个新的集合,首先想到的肯定是遍历,如下: List& ...

  2. Java8中的Stream流式操作 - 入门篇

    作者:汤圆 个人博客:javalover.cc 前言 之前总是朋友朋友的叫,感觉有套近乎的嫌疑,所以后面还是给大家改个称呼吧 因为大家是来看东西的,所以暂且叫做官人吧(灵感来自于民间流传的四大名著之一 ...

  3. HttpURLConnection的流式输出的缺陷和解决方法

    转自:http://www.mzone.cc/article/198.html 最近在用applet写文件上传控件的时候发现使用URLConnection来对服务器进行流式输出时的一些问题.我们通常要 ...

  4. 文件下载(StreamingHttpResponse流式输出)

    文件下载(StreamingHttpResponse流式输出) HttpResponse会直接使用迭代器对象,将迭代器对象的内容存储成字符串,然后返回给客户端,同时释放内存.可以当文件变大看出这是一个 ...

  5. Java的Stream流式操作

    前言 最近在实习,在公司看到前辈的一些代码,发现有很多值得我学习的地方,其中有一部分就是对集合使用Stream流式操作,觉得很优美且方便.所以学习一下Stream流,在这里记录一下. Stream是什 ...

  6. Java8——Stream流式操作的一点小总结

    我发现,自从我学了Stream流式操作之后,工作中使用到的频率还是挺高的,因为stream配合着lambda表达式或者双冒号(::)使用真的是优雅到了极致!今天就简单分(搬)享(运)一下我对strea ...

  7. 第46天学习打卡(四大函数式接口 Stream流式计算 ForkJoin 异步回调 JMM Volatile)

    小结与扩展 池的最大的大小如何去设置! 了解:IO密集型,CPU密集型:(调优)  //1.CPU密集型 几核就是几个线程 可以保持效率最高 //2.IO密集型判断你的程序中十分耗IO的线程,只要大于 ...

  8. Stream流式计算

    Stream流式计算 集合/数据库用来进行数据的存储 而计算则交给流 /** * 现有5个用户,用一行代码 ,一分钟按以下条件筛选出指定用户 *1.ID必须是偶数 *2.年龄必须大于22 *3.用户名 ...

  9. Stream流式编程

    Stream流式编程   Stream流 说到Stream便容易想到I/O Stream,而实际上,谁规定“流”就一定是“IO流”呢?在Java 8中,得益于Lambda所带来的函数式编程,引入了一个 ...

  10. Java1.8新特性 - Stream流式算法

    一. 流式处理简介   在我接触到java8流式数据处理的时候,我的第一感觉是流式处理让集合操作变得简洁了许多,通常我们需要多行代码才能完成的操作,借助于流式处理可以在一行中实现.比如我们希望对一个包 ...

随机推荐

  1. 在Ubuntu小设备上使用VSCode+SSH开发部署nicegui的Web应用,并设置系统开机自动启动应用

    在一些小的设备上跑Ubuntu系统,需要快速的开发和调整项目的时候,往往使用SSH进行远程的开发测试,这样可以避免传统的打包更新处理,能够快速的在实际环境上测试具体的内容.另外由于系统设备往往需要重启 ...

  2. Python实现回数

    题目:回数是指从左向右读和从右向左读都是一样的数,例如 12321,909.请利用 filter()滤掉非回数: 思路:要实现回数判断,主要是将输入的数找到其各个位置的值,然后判断前后相对应的位置是否 ...

  3. ToDesk云电脑游戏数量?高性能显卡云桌面

    玩游戏最怕遇到电脑配置跟不上,操作卡成狗不说,画面还一卡卡的,游戏体验极差. 最近被人安利了ToDesk的云电脑,可能是刚推出的,配置价格都很能打,浅用了一波拿来打APEX和荒野大镖客,体验有点惊喜到 ...

  4. Java高并发,ThreadPoolExecutor线程池技术

    Java当中的线程池是通过Executor这个框架接口来实现的,该框架当中用到了Executor,Executors工具类,ExecutorService,ThreadPoolExecutor Exe ...

  5. Java和Python的区别

    Java和Python区别 二者的区别有以下几点:1.Java必须显式声明变量名,而动态类型的Python不需要声明变量.2.Python虚拟机没有Java强,Java虚拟机是Java的核心,Pyth ...

  6. 用Python创建一个简单的Web服务器

    基本思路: 在浏览器地址栏通过输入本机地址:http://127.0.0.1:8000 能够访问我们自己创建的Web服务器,并且给浏览器返回一句Hello World 代码实现: 1 import s ...

  7. pyenv: no such command `virtualenv'

    当执行 pyenv virtualenv 3.6.10 env_3.6.10 命令创建新的python环境时提示 pyenv: no such command `virtualenv' larryma ...

  8. C语言指针一些常见的错误用法

    指针用的好犹如神助,用不好会让你叫苦连连,但大多数人是用不好指针的,所以后来的很多语言都把指针封装,屏蔽.比如JAVA,java是没有指针的,但是很多地方都用到指针,不过不对用户开放,语言的自身机制帮 ...

  9. Rust 的静态网站生成器「GitHub 热点速览」

    如果你做过个人博客网站,那么一定对静态网站生成器不陌生.无论是 Ruby 语言的 Jekyll.Go 语言的 Hugo.还是基于 React 的 Gatsby,这些工具都有庞大的用户群体.对于喜欢的人 ...

  10. NZOJ 模拟赛4

    T1 数字游戏 大家列队后,都觉得累了,于是一起坐到院子中的草地上休息.这时Anna突然想跟她的最大竞争对手Cici玩一个数字游戏,她要你编写程序帮助她取得胜利. 第i次游戏初始时有一个整数N_i(1 ...