二十Javascript API(一)

Posted 乘风xs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二十Javascript API(一)相关的知识,希望对你有一定的参考价值。

1. Atomics和SharedArrayBuffer

多个上下文访问 SharedArrayBuffer时,如果同时对缓冲区执行操作,就可能出现资源争用问题。Atomics API 通过强制同一时刻只能对缓冲区执行一个操作,可以让多个上下文安全地读写一个SharedArrayBuffer

1.1 SharedArrayBuffer

SharedArrayBufferArrayBuffer具有相同的API,其区别为,前者可以被任意多个执行上下文同时使用,后者必须在不同的执行上下文中进行切换

1.2原子操作基础

任何全局上下文中都有 Atomics 对象,这个对象上暴露了用于执行线程安全操作的一套静态方法,其中多数方法以一个 TypedArray 实例(一个 SharedArrayBuffer 的引用)作为第一个参数,以相关操作数作为后续参数。

算术与位操作方法

AtomicReadModifyWrite 操作。在底层,这些方法都会从 SharedArrayBuffer 中某个位置读取值,然后执行算术或位操作,最后再把计算结果写回相同的位置。这些操作的原子本质意味着上述读取、修改、写回操作会按照顺序执行,不会被其他线程中断。
Atomics.add()
Atomics.sub()
Atomics.or()
Atomics.and()
``Atomi

// 创建大小为 1 的缓冲区
let sharedArrayBuffer = new SharedArrayBuffer(1);
// 基于缓冲创建 Uint8Array
let typedArray = new Uint8Array(sharedArrayBuffer);
// 所有 ArrayBuffer 全部初始化为 0
console.log(typedArray); // Uint8Array[0]
const index = 0;
const increment = 5;
// 对索引 0 处的值执行原子加 5
Atomics.add(typedArray, index, increment);
console.log(typedArray); // Uint8Array[5]
// 对索引 0 处的值执行原子减 5
Atomics.sub(typedArray, index, increment);
console.log(typedArray); // Uint8Array[0]
原子读与写

浏览器的 javascript 编译器和 CPU 架构本身都有权限重排指令以提升程序执行效率,但多线程下的指令重排可能导致资源争用。
Atmoics API通过两种主要的方式解决该问题

  • 所有原子指令之间的顺序永远不会重排
  • 使用原子读或者原子保证所有指令都不会相对原子读/写重排
    Atomics.load()Atomics.store()还可以构建“代码围栏”。JavaScript引擎保证非原子指令可以相对于 load()或 store()本地重排,但这个重排不会侵犯原子读/写的边界。
原子交换

Atomics.exchange()执行简单的交换,以保证其他线程不会中断值的交换

const sharedArrayBuffer = new SharedArrayBuffer(4);
const view = new Uint32Array(sharedArrayBuffer);
// 在索引 0 处写入 3
Atomics.store(view, 0, 3);
// 从索引 0 处读取值,然后在索引 0 处写入 4
console.log(Atomics.exchange(view, 0, 4)); // 3
// 从索引 0 处读取值
console.log(Atomics.load(view, 0)); // 4

compareExchange()方法只在目标索引处的值与预期值匹配时才会执行写操作
如果值不匹配,compareExchange()调用则什么也不做.

const sharedArrayBuffer = new SharedArrayBuffer(4);
const view = new Uint32Array(sharedArrayBuffer);
// 在索引 0 处写入 5
Atomics.store(view, 0, 5);
// 从缓冲区读取值
let initial = Atomics.load(view, 0);
// 对这个值执行非原子操作
let result = initial ** 2;
// 只在缓冲区未被修改的情况下才会向缓冲区写入新值
Atomics.compareExchange(view, 0, initial, result);
// 检查写入成功
console.log(Atomics.load(view, 0)); // 25
const sharedArrayBuffer = new SharedArrayBuffer(4);
const view = new Uint32Array(sharedArrayBuffer);
// 在索引 0 处写入 5
Atomics.store(view, 0, 5);
// 从缓冲区读取值
let initial = Atomics.load(view, 0);
// 对这个值执行非原子操作
let result = initial ** 2;
// 只在缓冲区未被修改的情况下才会向缓冲区写入新值
Atomics.compareExchange(view, 0, -1, result);
// 检查写入失败
console.log(Atomics.load(view, 0)); // 5
原子Futex操作和锁

Atomics.wait(view, index, targetVal, time), 当索引index位置对应的值等于targetVal时,等待以获取锁,超时时间为time,超时顶部执行上下文会调用Atomics.notify()释放其中一个等待的线程。
Atmoics.notify(view, index, count), 允许count个线程继续在index操作。
Atomics.isLockFree()方法在高性能算法中可以用来确定是否有必要获取锁。

2.跨消息上下文

postMessage()方法接收 3 个参数:消息、表示目标接收源的字符串和可选的可传输对象的数组(只与工作线程相关)
onmessage的相应事件对象event包含三个方面的信息

  • data, postMessage()的第一个参数
  • origin, 发送消息的文档源
  • source, 发送消息的文档中window对象的代理

3. Encoding API

Encoding API 主要用于实现字符串与定型数组之间的转换。规范新增了 4 个用于执行转换的全局类:TextEncoderTextEncoderStreamTextDecoderTextDecoderStream

3.1 文本编码

Encoding API 提供了两种将字符串转换为定型数组二进制格式的方法:批量编码流编码。把字符串转换为定型数组时,编码器始终使用 UTF-8.
批量编码使用TextEncoder的实例

  • encode(),接受一个字符串参数,并以Uint8Array格式返回每个字符的UTF-8编码
  • encodeInto(),第一个参数为字符串str,第二个参数为目标Uint8Array,将str写入目标Uint8Array,返回一个字典,该字典包含readwritten两个属性,分别表示成功读取和写入的字符。

流编码使用TextEncoderStream的实例

3.2 文本解码

批量解码-----TextDecoder

  • decode(), 不关心传入的是哪种定型数组,与 TextEncoder 不同,TextDecoder 可以兼容很多字符编码。

流解码-----TextDecoderStream

4. File API 与Blob API

4.1 File类型

File API 仍然以表单中的文件输入字段为基础,但是增加了直接访问文件信息的能力。每个File对象包含以下只读属性

  • name, 本地系统中的文件名
  • size, 以字节计算的文件大小
  • type, 包含文件MIME类型的字符串
  • lastModifiedDate,文件最后修改的时间字符串,仅仅Chrome有

4.2 FileReader类型

异步读取文件,具有以下的方法

  • readAsText(file, encoding), 从文件中读取纯文本内容,并保存在result属性中
  • readAsDataURL(file),读取文件并将内容的数据URL保存在result属性中
  • readAsBinaryString(file), 读取文件并将每个字符的二进制数据保存在result属性中
  • readAsArrayBuffer(file), 读取文件,并将内容以ArrayBuffer形式保存在result属性中

支持的事件处理程序

  • progress, 表示还有更多数据,约没50毫秒触发一次,包含lengthComputableloadedtotal等信息,还可以通过result属性读取已经读到的数据。
  • error, 发生错误,只包含一个信息code。这个错误码的值可能是
    • 1(未找到文件)
    • 2(安全错误)
    • 3(读取被中断)
    • 4(文件不可读)
    • 5(编码错误)
  • load, 读取完成

4.3 FileReaderSync 类型

FileReaderSync 类型就是 FileReader 的同步版本。这个类型拥有与 FileReader
相同的方法,只有在整个文件都加载到内存之后才会继续执行。FileReaderSync 只在工作线程中可用,因为如果读取整个文件耗时太长则会影响全局。

// worker.js
self.omessage = (messageEvent) => 
	 const syncReader = new FileReaderSync();
	 console.log(syncReader); // FileReaderSync 
	 // 读取文件时阻塞工作线程
	 const result = syncReader.readAsDataUrl(messageEvent.data);
	 // PDF 文件的示例响应
	 console.log(result); // data:application/pdf;base64,JVBERi0xLjQK...
	 // 把 URL 发回去
	 self.postMessage(result);
; 

4.4 Blob与部分读取

读取部分文件,File对象具有slice(startByteIndex, endByteIndex)方法,返回一个Blob实例。BlobFile的超类

blob 表示二进制大对象(binary larget object),是 JavaScript 对不可修改二进制数据的封装类型。包含字符串的数组、ArrayBuffers、ArrayBufferViews,甚至其他 Blob 都可以用来创建 blob。Blob构造函数可以接收一个 options 参数,并在其中指定 MIME 类型.

Blob 对象有一个 size 属性和一个 type 属性,还有一个 slice()方法用于进一步切分数据,也可以使用 FileReader 从 Blob 中读取数据。

4.5 对象URL和Blob

创建对象URL,使用 window.URL.createObjectURL()方法并传入 File 或 Blob 对象。
释放对象URL, 使用window.URL.revokeObjectURL(url)

4.6 读取拖放文件

在页面创建放置目标后,被放置的文件可以通过事件的 event.dataTransfer.files 属性读到,这个属性保存着一组 File 对象。
必须取消 dragenterdragoverdrop的默认行为

5.媒体元素

视频和音频的处理分别使用\\<video>\\<audio>,主要属性有src/width/height/poster/\\<source>.

5.1 属性

属性数据类型说明
autoplayboolean取得或者设置autoplay标签,下载完自动开始播放
bufferedTimeRanges表示已经下载缓冲的时间范围
bufferedBytesByteRanges表示已经下载缓冲的字节范围
bufferingRateinteger平均每秒下载的位数
bufferingThrottledboolean表示缓冲是否有被浏览器截流
controlsboolean取得或设置controls属性,用于显示或者隐藏控件
currentLoopinteger已经循环播放的次数
currentSrcstring播放媒体的url
currentTimefloat已经播放的秒数
defaultPlaybackRatefloat默认回放速率,默认1.0秒
durationfloat总秒数
endedbooelan是否播放完
loopboolean是否循环播放
mutedboolean是否静音
networkStateinteger当前网络连接状态,0空,1加载中,2加载元数据,3加载了第一帧,4加载完成
pausedboolean是否暂停
playbackRatefloat设置播放速率
playedTimeRanges已经播放的时间范围
readyStateinteger是否已经准备就绪,0媒体不可用,1可以显示当前帧,2可以开始播放,3可以从头播放到尾
seekableTimeRanges可以跳转的时间范围
seekingboolean是否正移动到媒体的新位置
srcstring媒体资源url,随时可以改写
startfloat取得或者设置媒体文件中的位置,以秒为单位,从该处开始播放
totalBytesinteger总大小
videoHeight/videoWidthinteger<video>独有,高度和宽度
volumefloat当前音量值,0.0-1.0

5.2事件

事件何时触发
abort下载被中断
canplay可以开始回放,readyState === 2
canplaythrough回放可以继续,readyState === 3
canshowcurrentframe已经下载当前帧,readyState === 1
dataunavailable不能回放,readyState=== 0
durationchangeduration属性发生变化
emptied网络连接关闭
empty发生了错误,组织媒体下载
ended媒体已经播放完一遍,并且停止了
error下载期间发生网络错误
loadeddata第一帧已经下载
loadedmetadata元数据已经下载
loadstart下载已经开始
pause回放已经暂停
paly媒体收到开始播放的请求
playing媒体已经开始播放
progress下载中
ratechange播放速率发生变化
seeked跳转已经结束
seeking回放已经移动到新的位置
stalled浏览器尝试下载,但是尚未收到数据
timeupdatecurrentTime被非常规或者意外地修改了
volumechangevolume或者muted属性被修改
waiting回放暂停,以下载更多的数据

5.3检测编解码器

<video>和<audio>元素都有一个canPlayType()方法,接受一个表示MIME类型的字符串(还可以额外包含编解码器),返回probably/maybe/空字符串三者中的一个。

const audio = document.getElementById('audio-player');
if (audio.canPlayType("audio/mpeg")
	//...

if (audio.canPlayType("audio/ogg;codecs=\\"vorbis\\""))
	//...

5.4 音频类型

Audio构造函数,与Image类似,但是不需要插入文档即可工作

let audio = new Audio("sound.mp3");
EventUtil.addHandler(audio, "canplaythrough", function(event)
	audio.play();
);

6. 原生拖放

6.1拖放事件

被拖放元素的身上会依次触发dragstart/drag/dragend
目标元素身上会依次触发dragenter/dragover/dragleave或者drop

6.2 自定义拖放目标

如果把元素拖动到不允许放置的目标上,无论用户动作是什么都不会触发 drop 事件。不过,通过event.preventDefault()覆盖dragenter dragover 事件的默认行为,可以把任何元素转换为有效的放置目标。

let droptarget = document.getElementById("droptarget");
droptarget.addEventListener("dragover", (event) => 
 	event.preventDefault();
 	//...
);
droptarget.addEventListener("dragenter", (event) => 
 	event.preventDefault();
 	//...
);

6.3 DataTransfer对象

dataTransfer 对象,用于从被拖动元素向放置目标传递字符串数据。因为这个对象是event 的属性,所以在拖放事件的事件处理程序外部无法访问 dataTransfer
dataTransfer 对象有两个主要方法:getData() setData()。顾名思义,getData()用于获取 setData()存储的值。setData()的第一个参数以及 getData()的唯一参数是一个字符串

6.4 dropEffect 和 effectAllowed

dataTransfer 对象不仅可以用于实现简单的数据传输,还可以用于确定能够对被拖动元素和放置目标执行什么操作。为此,可以使用两个属性:dropEffecteffectAllowed
dropEffect 属性可以告诉浏览器允许哪种放置行为,有以下 4 种可能的值:

  • none, 被拖动元素不能放到这里。这是除文本框之外所有元素的默认值。
  • move, 被拖动元素应该移动到放置目标。
  • copy,被拖动元素应该复制到放置目标。
  • link, 表示放置目标会导航到被拖动元素(仅在它是 URL 的情况下)。

为了使用 dropEffect 属性,必须在放置目标的 ondragenter 事件处理程序中设置它,并且同时设置 effectAllowed,否则 dropEffect 属性也没有用
effectAllowed 属性表示对被拖动元素是否允许 dropEffect,有如下几个可能的值:

  • uninitialized, 没有给被拖动元素设置动作。
  • none, 被拖动元素上没有允许的操作。
  • copy, 只允许"copy"这种 dropEffect。
  • link, 只允许"link"这种 dropEffect。
  • move, 只允许"move"这种 dropEffect。
  • copyLink, 允许"copy"和"link"两种 dropEffect。
  • copyMove, 允许"copy"和"move"两种 dropEffect。
  • linkMove, 允许"link"和"move"两种 dropEffect。
  • all, 允许所有 dropEffect。
    必须在 ondragstart 事件处理程序中设置这个属性

6.5 可拖动能力

draggable 属性,表示元素是否可以拖动。图片和链接的 draggable 属性自动被设置为 true,而其他所有元素此属性的默认值为 false

6.6 其他成员

html5 规范还为 dataTransfer 对象定义了下列方法:

  • addElement(element):为拖动操作添加元素。
  • clearData(format):清除以特定格式存储的数据。
  • setDragImage(element, x, y):允许指定拖动发生时显示在光标下面的图片。
  • types:当前存储的数据类型列表。

好书推荐介绍 JavaScript 从1995年到2015年的发展历程 | 《JavaScript二十年》

目录

一、JavaScript的发展历史了解一下

你好,我是小雨青年,一名程序员。

今天为你推荐的书籍是《JavaScript二十年》。

很少能有一本书能讲述一种开发语言的发展,恰巧《JavaScript二十年》就是这样一本书。

本书分为四个部分,介绍了 JavaScript 从1995年到2015年的发展过程。

本书中提到的参考资料的链接,到现在都是可以访问的,也就是说,我们作为读者可以通过查阅资料的方式亲眼见证过去发生过的历史。

JavaScript 诞生之出,Robert Cailliau 称 JavaScript 为"计算机史上最可怕的糟粕",并说:“我只知道一种比C 更糟糕的编程语言,那就是 JavaScript”。

AJAX 和使用它构建社交媒体应用成为了 Web 2.0 的标志。

另外,本文的附录做得很棒,其中附录F甚至是《1995年12月4日关于 JavaScript 发布的新闻稿》。

二、书籍信息

书名JavaScript二十年
作者【美】Allen Wirfs-Brock / 【美】Brendan Eich
出版社电子工业出版社
ISBN9787121408687

三、推荐人群

  • 希望了解JavaScript的技术八卦历史的开发者
  • 前端工程师

四、相关推荐

以上是关于二十Javascript API(一)的主要内容,如果未能解决你的问题,请参考以下文章

什么是原子操作?在 Java Concurrency API 中有哪些原 子类(atomic classes)?

什么是原子操作?在 Java Concurrency API 中有哪些原 子类(atomic classes)?

(二十八)加锁

好书推荐介绍 JavaScript 从1995年到2015年的发展历程 | 《JavaScript二十年》

好书推荐介绍 JavaScript 从1995年到2015年的发展历程 | 《JavaScript二十年》

Swift系列二十八 - 数组