项目中在做关于流的处理,后端会返回一个流的形式的数据,一直在想用什么方式请求比较好,后来发现用fetch来处理是最好的。
关于fetch我之前了解的不是很多,只知道fetch也是接口请求方式的一种,为了关于这个流,我就去官网学习了一下,发现好像东西挺多的。主要英文官网太难啃了,主要还是看了中文类的文档(www.w3cschool.cn/fetch_api/),等有时间了,英文的文档需要好好学习一下。
一:fetch请求
关于fetch中文官网是这样说的
二:使用fetch
关于fetch的使用中文官网是这样说的
在项目中使用fetch请求,其中属性在官网中都可以找到说明。
fetch(url,{ method:'post',headers:{
'Content-Type': 'application/json'},
credentials: 'include',
body: JSON.stringify(params)}).then(response=>{})
三:处理fetch中的流
既然是处理流,用的就是递归函数来读取和处理流数据,然后对流进行解码并分割处理,切分完成后再继续读取下一段流数据。因为fetch方法是允许去跟踪下载进度的,使用 response.body 属性,与 response.text(),response.json() 和其他方法不同,response.body 给予了对进度读取的完全控制,我们可以随时计算下载了多少。当所有的流都处理完成后就需要退出递归函数,reader.read()使用后的结果是一个具有两个属性的对象,一个是done,一个是value,
- done :当所有的流读取完成时值为 true ,否则为 false
- value :字节的类型化数组 :Uint8Array
正常执行fetch后,不是调用response.json()而是获得了一个流读取器response.body.getReader()。
用递归函数来读取并处理读取到的流
// 创建文本解码器并获取可读流
const decoder = new TextDecoder();
const reader = response.body.getReader();
var content=''
// 递归函数来读取并处理流数据
const read = () => {
reader.read().then(({ done, value }) => {
// console.log('读取', done, value)
if (done) return
// 解码并分割事件
const text = decoder.decode(value);
const events = text.split('\n');
content +=text
// 继续读取下一段流数据
read();
})
};
// 开始读取流数据
read();
在递归中接受响应的数据流,当所有的响应的数据流加载完成后,也就是done的值为true的时候,说明所有的流都加载完成,可以进行下一步处理,退出递归或者处理其他的。
因为需求是要类似于那种文字输出有停顿感的样子,所以用fetch来处理,后端给的流会处理好输出的数据速度,只要在使用的时候注意递归的方式,处理好递归中的流数据,就可以啦
createdValue(){
const params={
prompt:prompt,
contextId:contextId
}
fetch(url,{ method:'post',headers:{
'Content-Type': 'application/json'},
credentials: 'include',
body: JSON.stringify(params)}).then(response=>{
// 创建文本解码器并获取可读流
const decoder = new TextDecoder();
const reader = response.body.getReader();
var content=''
// 递归函数来读取并处理流数据
const read = () => {
reader.read().then(({ done, value }) => {
// console.log('读取', done, value)
if (done) return;
// 解码并分割事件
const text = decoder.decode(value);
const events = text.split('\n');
content+=text
// 继续读取下一段流数据
read();
})
};
// 开始读取流数据
read();
}).catch(error => {
console.error(error);
});