背景:开发一个Ai项目时,请求接口后返回的数据是流式的 TypedArray 类型
一、ArrayBuffer类型数据
1. 定义:
-
ArrayBuffer 是一个用于表示固定长度的原始二进制数据缓冲区的对象。
-
它本身不提供直接操作数据的方法
- 用途:
-
主要用于存储二进制数据。
-
需要通过
TypedArray或 DataView 来访问和操作其内容。
3. 特性:
-
一旦创建,大小固定,不能调整。
-
只能通过视图(如 TypedArray 或 DataView)来读取或写入数据。
- 创建示例:
const buffer = new ArrayBuffer(16); // 创建一个16字节的缓冲区
二、TypedArray类型数据
- 定义:
-
TypedArray是一组类型化数组的集合,用于在ArrayBuffer上操作特定类型的数值数据。 -
包括Int8Array,
Uint8Array, Uint16Array, Int32Array, Uint32Array...等等。
- 用途:
-
提供了一种在
ArrayBuffer上操作特定类型数据的方式。 -
允许以特定数值类型(如整数、浮点数)来读取和写入数据。
第一步:使用new Unit8Array() 处理
requestTask.onChunkReceived(response=>{
let arrayBuffer = response.data /* TypedArray类型*/
const arrayBufferss = new Uint8Array(arrayBuffer) /*使用new Uint8Array()转化*/
})
第二步:使用String.fromCharCode() 转字符串
// 流式返回数据
requestTask.onChunkReceived(response=>{
// console.log(response);
let arrayBuffer = response.data /* TypedArray类型*/
const arrayBufferss = new Uint8Array(arrayBuffer) /* 使用new Uint8Array()转化*/
let string = ''
for(let i = 0; i < arrayBufferss.length; i++){
// unicode字符, 将Unicode码点值转换为对应的字符,并返回一个新的字符串
string += String.fromCharCode(arrayBufferss[i])
}
})
第三步:使用escape和decodeURIComponent解决乱码问题
先编码,再进行解码
let buffer = ''
// 流式返回数据
requestTask.onChunkReceived(response=>{
// console.log(response);
let arrayBuffer = response.data /* TypedArray类型*/
const arrayBufferss = new Uint8Array(arrayBuffer) /* 使用new Uint8Array()转化*/
let string = ''
for(let i = 0; i < arrayBufferss.length; i++){
// unicode字符, 将Unicode码点值转换为对应的字符,并返回一个新的字符串
string += String.fromCharCode(arrayBufferss[i])
}
// 编码和解码
buffer += decodeURIComponent(escape(string))
console.log(buffer);
})
第四步:和后端返回数据保持一致
// 流式返回数据
requestTask.onChunkReceived(response=>{
// console.log(response);
let arrayBuffer = response.data /* TypedArray类型*/
const arrayBufferss = new Uint8Array(arrayBuffer) /* 使用new Uint8Array()转化*/
let string = ''
for(let i = 0; i < arrayBufferss.length; i++){
// unicode字符, 将Unicode码点值转换为对应的字符,并返回一个新的字符串
string += String.fromCharCode(arrayBufferss[i])
}
// 编码和解码
buffer += decodeURIComponent(escape(string))
// 循环检查buffer里面是否包含换行符
while(buffer.includes('\n')){
const index = buffer.indexOf('\n')
// 留下需要的
const chunk = buffer.slice(0,index)
// 去掉已经处理过
buffer = buffer.slice(index + 1)
}
})
第五步:处理不需要的字符串
// 流式返回数据
requestTask.onChunkReceived(response=>{
// console.log(response);
let arrayBuffer = response.data /* TypedArray类型*/
const arrayBufferss = new Uint8Array(arrayBuffer) /* 使用new Uint8Array()转化*/
let string = ''
for(let i = 0; i < arrayBufferss.length; i++){
// unicode字符, 将Unicode码点值转换为对应的字符,并返回一个新的字符串
string += String.fromCharCode(arrayBufferss[i])
}
// 编码和解码
buffer += decodeURIComponent(escape(string))
// 循环检查buffer里面是否包含换行符
while(buffer.includes('\n')){
const index = buffer.indexOf('\n')
// 留下需要的
const chunk = buffer.slice(0,index)
// 去掉已经处理过
buffer = buffer.slice(index + 1)
// 判断以data:开头并且不含有data: [DONE]
if(chunk.startsWith('data: ') && !chunk.includes('[DONE]')){
const jsonData = JSON.parse(chunk.replace('data: ',''))
}
}
})