这是我参与8月更文挑战的第4天,活动详情查看:8月更文挑战
一、基础知识
1.1 ArrayBuffer
ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区。ArrayBuffer 不能直接操作,而是要通过类型数组对象 或 DataView 对象来操作,它们会将缓冲区中的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容。
ArrayBuffer 简单说是一片内存,但是你不能直接用它。这就好比你在 C 里面,malloc 一片内存出来,你也会把它转换成 unsigned_int32 或者 int16 这些你需要的实际类型的数组/指针来用。
这就是 JS 里的 TypedArray 的作用,那些 Uint32Array 也好,Int16Array 也好,都是给 ArrayBuffer 提供了一个 “View”,MDN 上的原话叫做 “Multiple views on the same data”,对它们进行下标读写,最终都会反应到它所建立在的 ArrayBuffer 之上。
语法
new ArrayBuffer(length)
- 参数:length 表示要创建的 ArrayBuffer 的大小,单位为字节。
- 返回值:一个指定大小的 ArrayBuffer 对象,其内容被初始化为 0。
- 异常:如果 length 大于
Number.MAX_SAFE_INTEGER(>= 2 ** 53)或为负数,则抛出一个RangeError异常。
示例
下面的例子创建了一个 8 字节的缓冲区,并使用一个 Int32Array 来引用它:
let buffer = new ArrayBuffer(8);
let view = new Int32Array(buffer);
从 ECMAScript 2015 开始,ArrayBuffer 对象需要用 new 运算符创建。如果调用构造函数时没有使用 new,将会抛出 TypeError 异常。比如执行该语句 let ab = ArrayBuffer(10) 将会抛出以下异常:
VM109:1 Uncaught TypeError: Constructor ArrayBuffer requires 'new'
at ArrayBuffer (<anonymous>)
at <anonymous>:1:10
对于一些常用的 Web API,如 FileReader API 和 Fetch API 底层也是支持 ArrayBuffer,这里我们以 FileReader API 为例,看一下如何把 File 对象读取为 ArrayBuffer 对象:
const reader = new FileReader();
reader.onload = function(e) {
let arrayBuffer = reader.result;
}
reader.readAsArrayBuffer(file);
1.2 Unit8Array
Uint8Array 数组类型表示一个 8 位无符号整型数组,创建时内容被初始化为 0。创建完后,可以以对象的方式或使用数组下标索引的方式引用数组中的元素。
语法
new Uint8Array(); // ES2017 最新语法
new Uint8Array(length); // 创建初始化为0的,包含length个元素的无符号整型数组
new Uint8Array(typedArray);
new Uint8Array(object);
new Uint8Array(buffer [, byteOffset [, length]]);
示例
// new Uint8Array(length);
var uint8 = new Uint8Array(2);
uint8[0] = 42;
console.log(uint8[0]); // 42
console.log(uint8.length); // 2
console.log(uint8.BYTES_PER_ELEMENT); // 1
// new TypedArray(object);
var arr = new Uint8Array([21,31]);
console.log(arr[1]); // 31
// new Uint8Array(typedArray);
var x = new Uint8Array([21, 31]);
var y = new Uint8Array(x);
console.log(y[0]); // 21
// new Uint8Array(buffer [, byteOffset [, length]]);
var buffer = new ArrayBuffer(8);
var z = new Uint8Array(buffer, 1, 4);
// new TypedArray(object);
// 当传入一个 object 作为参数时,就像通过 TypedArray.from()
// 方法创建一个新的类型化数组一样。
var iterable = function*(){ yield* [1,2,3]; }();
var uint8 = new Uint8Array(iterable);
// Uint8Array[1, 2, 3]
通过ArrayBuffer的格式读取本地数据
document.getElementById('f').addEventListener('change', function (e) {
const file = this.files[0];
const fileReader = new FileReader();
fileReader.onload = function () {
const result = fileReader.result;
console.log(result)
}
fileReader.readAsArrayBuffer(file);
}, false);
通过ArrayBuffer的格式读取Ajax请求数据
- 通过xhr.responseType = "arraybuffer" 指定响应的数据类型
- 在onload回调里打印xhr.response
前端
const xhr = new XMLHttpRequest();
xhr.open("GET", "ajax", true);
xhr.responseType = "arraybuffer";
xhr.onload = function () {
console.log(xhr.response)
}
xhr.send();
Node端
const app = new Koa();
app.use(async (ctx) => {
if (pathname = '/ajax') {
ctx.body = 'hello world';
ctx.status = 200;
}
}).listen(3000)
ArrayBuffer转json
ws.onmessage = function (evt) {
// evt.data是ArrayBuffer
// 将其转换为uint8字节流
var uint8_msg = new Uint8Array(evt.data);
// 解码成字符串
var decodedString = String.fromCharCode.apply(null, uint8_msg);
console.log(decodedString);
// parse,转成json数据
var data = JSON.parse(decodedString);
console.log(data);
};
另一种方法,utf-8防止乱码
let content = file.data;//arraybuffer类型数据
let resBlob = new Blob([content])
let reader = new FileReader()
reader.readAsText(resBlob, "utf-8")
reader.onload = () => {
let res = JSON.parse(reader.result)
console.log(JSON.parse(reader.result))
}