原子和数组共享缓存(ATOMICS AND SharedArrayBuffer)
当SharedArrayBuffer被多个上下文访问,并且操作同一个缓存区,会出现资源竞争的问题,原子API允许多个上下文安全的读写一个缓存区,强制对缓存区的操作同一时间只能有一个,Atomics API在ES2017规范中被定义。
SharedArrayBuffer
SharedArrayBuffer与ArrayBuffer具有相同的API,主要不同点是,ArrayBuffer必须在执行上下文中传递,SharedArrayBuffer可以被多个上下文操作。
共享内存给多个上下文意味着可以实现线程并发,传统的JavaScript操作不保护内存中的资源竞争
Atomics基础
Atomics对象存在于全局上下文中,并且暴露一套关于线程安全操作的静态方法,这些方法大多数取TypeArray的实例作为第一个参数并将相关的操作数作为其他的参数。
Atomics的读和写
Atomics API解决资源竞争主要通过以下这两种方式:
1、所有Atomics指令永远不会让其他指令重排
2、使用Atomic读或者Atomic写,可以保证指令不会重排,这意味着所有指令在Atomic的读写完成之前都不能开始。
调用Atomics.load()原子读取,Atomics.store()原子写入
编码API
Encoding API可以允许字符串和某类型的数组相互转换,该规范引入了四个执行转换的全局类TextEncoder、 TextEncoderStream、 TextDecoder、 TextDecoderStream。
字符编码-bulk
Encoding API支持两种方法把字符串转为某类型数组,大量字符编码(bulk encoding)和流编码(stream encoding),编码通常采用UTF-8格式。
bulk编码意味着JavaScript引擎将同步编码所有字符串,字符串如果很长,那么也会非常消耗资源,bulk encoding通过以下这种写法实现字符串编码
//初始化
const textEncoder = new TextEncoder()
const text = 'good'
const encodeText = textEncoder.encode(text)
console.log(encodeText);
编码后得到一个UInt8类型的数组
encoder也支持特殊的字符,比如表情
//初始化
const textEncoder = new TextEncoder()
const text = '😄'
const encodeText = textEncoder.encode(text)
console.log(encodeText);
字符编码-stream
TextEncoderStream仅仅是一个TransformStream形式的TextEncoder,通过流编码将字符流解码管道化,产生编码后的文本块流
async function* chars() {
const decodedText = 'foo';
for (let char of decodedText) {
yield await new Promise((resolve) => setTimeout(resolve, 1000, char));
}
}
const decodedTextStream = new ReadableStream({
async start(controller) {
for await (let chunk of chars()) {
controller.enqueue(chunk);
}
controller.close();
}
});
const encodedTextStream = decodedTextStream.pipeThrough(new TextEncoderStream());
const readableStreamDefaultReader = encodedTextStream.getReader();
(async function() {
while(true) {
const { done, value } = await readableStreamDefaultReader.read();
if (done) {
break;
} else {
console.log(value);
}
}
})();
字符解码-bulk
接着之前的bulk编码,对应解码,把把编码好的数组放到解码器里面
//初始化
const textEncoder = new TextEncoder()
const text = '😄'
const encodeText = textEncoder.encode(text)
console.log(encodeText);
//初始化解码器
const textDecoder = new TextDecoder()
const decodeText = textDecoder.decode(encodeText)
console.log(decodeText);
字符解码-stream
也和之前差不多,需要进行管道化
async function* chars() {
// Each chunk must exist as a typed array
const encodedText = [102, 111, 111].map((x) => Uint8Array.of(x));
for (let char of encodedText) {
yield await new Promise((resolve) => setTimeout(resolve, 1000, char));
}
}
const encodedTextStream = new ReadableStream({
async start(controller) {
for await (let chunk of chars()) {
controller.enqueue(chunk);
}
controller.close();
}
});
const decodedTextStream = encodedTextStream.pipeThrough(new TextDecoderStream());
const readableStreamDefaultReader = decodedTextStream.getReader();
(async function() {
while(true) {
const { done, value } = await readableStreamDefaultReader.read();
if (done) {
break;
} else {
console.log(value);
}
}
})();
二进制对象和文件API
很早以前,web应用的主要痛点之一就是不能操作用户电脑上的文件,2000年之前只有一种解决方式,在元素加上类型属性 type="file" ,二进制对象和文件API的出现解决了问题
文件类型
文件API是仍然基于文件输入的表单域,添加了直接访问文件信息的能力,HTML5为文件输入元素添加了文件集合到DOM上。一但一个或者多个文件被选中,文件集合包含一系列代表每个文件的文件对象,每个文件对象都有这么几个只读的属性:
name:在本地系统的文件名
size:文件的大小(单位:字节)
type:字符串,包含MIME的文件类型
lastModifiedDate:字符串,表示最后一次的修改时间(只有Chrome浏览器可以实现)
文件读取器类型
文件读取器(FileReader)类型,代表一种异步的文件读取机制,FileReader提供了几个方法读取文件数据
readAsText(file, encoding):读文件作为默认文本并且存储到result属性中,第二个参数是编码类型,可选参数
readAsURL(file):读取文件并且存储到result属性表示数据的URI
readAsBinaryString(file):读取文件并且把字符串的每个字符串表示为字节数据存储到result属性中