问题描述:
一开始怎么也接收不到数据,在vite.config配置的代理如下
server: {
proxy: {
'api': {
target:'http://172.21.80.115:10021',
changeOrigin:true,
rewrite: (path) => path.replace(/^\/sage-ddiligence-application/, '/sage-ddiligence-application'), // 重写路径
}
}
}
把api那里改成
server: {
proxy: {
'/sage-ddiligence-application': {
target:'http://172.21.80.115:10021',
changeOrigin:true,
rewrite: (path) => path.replace(/^\/sage-ddiligence-application/, '/sage-ddiligence-application'), // 重写路径
}
}
}
就可以了,原因暂时还不知道
现在是不知道怎么接收流式数据,接收到的数据仍然是一次性显示出来的
const recept= async()=>{
let res=await axios.get('/sage-ddiligence-application/customers/stream',{
responseType: 'stream'
})
console.log(res.data)
}
recept()
解决方法:
(仅用两个数据渲染作示例)
1.发起 fetch
请求
- 使用
fetch
函数向服务器请求数据流,其中/sage-ddiligence-application/customers/stream
是数据流的URL。 - 设置请求方法为
GET
,并指定Content-Type
为application/json;charset=UTF-8
,告诉服务器期望的响应数据类型是JSON。
const resp = await fetch('/sage-ddiligence-application/customers/stream', {
method: 'GET',
headers: {
"Content-Type": "application/json;charset=UTF-8",
},
});
2.获取响应流的读取器:
- 通过
await resp.body.getReader()
获取响应体(resp.body
)的读取器(reader
),这个读取器用于逐块读取数据流。
const reader = await resp.body.getReader();
3.创建 TextDecoder
实例:
TextDecoder
用于将流中接收到的字节序列(通常是Uint8Array
)解码成字符串。这里使用默认的UTF-8
编码。const decoder = new TextDecoder();
4.定义并调用 read
函数:
read
是一个异步递归函数,用于从流中读取数据块,处理它们,并等待下一个数据块的到来。- 使用
await reader.read()
读取流中的下一块数据。reader.read()
返回一个Promise,该Promise解析为一个对象,其中包含两个属性:done
和value
。done
是一个布尔值,表示是否已经读取了流的所有数据。value
是一个Uint8Array
,包含了读取到的数据块。 - 如果
done
为true
,表示流结束,打印 "Stream completed" 并返回,递归调用停止。 - 使用
decoder.decode(value, {stream: true})
将读取到的数据块value
解码成字符串。设置{stream: true}
表示解码器应保持内部状态,以便正确处理跨多个块的字符。
async function read() {
const {done, value} = await reader.read();
if (done) {
console.log("Stream completed");
return;
}
const str = decoder.decode(value, {stream: true});
5.处理解码后的字符串:
- 将解码后的字符串
str
按换行符分割成多行,每行代表一个JSON对象(假设服务器按行发送JSON对象)。 - 遍历每行字符串,使用
JSON.parse(line)
将其解析成JSON对象data
。 - 根据
data.attribute
的值,将data.value
存储到相应的响应式变量中(例如,customerCode
或customerNames
)。 -
使用
str.split('\n')
将字符串str
分割成数组:这里,str
是一个包含多行的字符串,每行可能代表一个独立的JSON对象。通过使用.split('\n')
方法,我们可以根据换行符将这个字符串分割成一个数组,数组中的每个元素都是原字符串中的一行。 -
对结果数组使用
.forEach(...)
进行迭代:分割操作返回的数组可以使用.forEach
方法。这个方法接受一个回调函数作为参数,该回调函数会被数组中的每个元素依次调用。在这个回调函数内,你可以处理每一行字符串,解析JSON并更新相应的响应式变量。 -
//假设每个json对象都是换行传过来的 str.split('\n').forEach(line => { if (line) { const data = JSON.parse(line); if (data.attribute === 'customerCode') { customerCode.value = data.value; } else if (data.attribute === 'customerName') { customerNames.value.push(data.value); } } });
6.递归读取下一个数据块:
- 在
read
函数的末尾,递归调用read()
函数本身,开始读取下一个数据块,直到整个流被读完。
7.完整代码
<script>
async function getData() {
const resp = await fetch('/sage-ddiligence-application/customers/stream', {
method: 'GET',
headers: {
"Content-Type": "application/json;charset=UTF-8",
},
});
const reader = await resp.body.getReader();
const decoder = new TextDecoder();
async function read() {
const {done, value} = await reader.read();
if (done) {
console.log("Stream completed");
return;
}
const str = decoder.decode(value, {stream: true});
//假设每个json对象都是换行传过来的
str.split('\n').forEach(line => {
if (line) {
const data = JSON.parse(line);
if (data.attribute === 'customerCode') {
customerCode.value = data.value;
} else if (data.attribute === 'customerName') {
customerNames.value.push(data.value);
}
}
});
read();
}
read();
}
getData()
</script>
<template>
<div class="table-cell">{{ customerCode }}</div>
<div class="table-cell">{{ customerNames.join('') }}</div>
</template>