JavaScript红宝书15-JavaScript常用API(JavaScript APIs)

122 阅读4分钟

原子和数组共享缓存(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属性中