二十、Javascript API (二)

二十、Javascript API (二)_第1张图片

1.Notification API

1.1 权限

Notifications API 有被滥用的可能,因此默认会开启两项安全措施:

  • 通知只能在运行在安全上下文的代码中被触发
  • 通知必须按照每个源的原则明确得到用户允许

页面可以使用全局对象 Notification 向用户请求通知权限。这个对象有一个 requestPemission()方法,该方法返回一个期约,用户在授权对话框上执行操作后这个期约会解决。granted值意味着用户明确授权了显示通知的权限。除此之外的其他值意味着显示通知会静默失败。如果用户拒绝授权,这个值就是denied。一旦拒绝,就无法通过编程方式挽回,因为不可能再触发授权提示。

Notification.requestPermission()
 .then((permission) => {
	 console.log('User responded to permission request:', permission);
 });

1.2 显示和隐藏通知

Notification 构造函数用于创建和显示通知。其第一个参数为显示的标题,第二个可选参数为options配置项,包括设置通知的主体、图片和振动等。调用这个构造函数返回的 Notification 对象的 close()方法可以关闭显示的通知。

const n = new Notification('will close in 1000ms!', {
 body: 'Body text!',
 image: 'path/to/image.png',
 vibrate: true
}); 
setTimeoute(() => n.close(), 1000);

1.3 通知生命周期回调

  • onshow 在通知显示时触发;
  • onclick 在通知被点击时触发;
  • onclose 在通知消失或通过 close()关闭时触发;
  • onerror 在发生错误阻止通知显示时触发。
const n = new Notification('foo');
n.onshow = () => console.log('Notification was shown!');
n.onclick = () => console.log('Notification was clicked!');
n.onclose = () => console.log('Notification was closed!');
n.onerror = () => console.log('Notification experienced an error!'); 

2. PageVisibility API

Page Visibility API 旨在为开发者提供页面对用户是否可见的信息。
document.visibilityState 值,有三个hidden/visible/prerender,表示下面 4 种状态之一:

  • 页面在后台标签页或浏览器中最小化了。
  • 页面在前台标签页中。
  • 实际页面隐藏了,但对页面的预览是可见的(例如在 Windows 7 上,用户鼠标移到任务栏图标上会显示网页预览)。
  • 页面在屏外预渲染。

visibilitychange 事件,该事件会在文档从隐藏变可见(或反之)时触发。
document.hidden ,布尔值,表示页面是否隐藏,是为了向后兼容才继续被浏览器支持的,应该优先使用 document.visibilityState检测页面可见性。

3. Streams API

Streams API 是为了解决一个简单但又基础的问题而生的:Web 应用如何消费有序的小信息块而不是大块信息?主要有两种应用场景:

  • 大块数据可能不会一次性都可用。网络请求的响应就是一个典型的例子。
  • 大块数据可能需要分小部分处理。视频处理、数据压缩、图像编码和 JSON 解析都是可以分成小部分进行处理,而不必等到所有数据都在内存中时再处理的例子

3.1 基本概念

Streams API 实际是为映射低级 I/O 原语而设计,包括适当时候对字节流的规范化,定义了三种流:

  • 可读流,可以通过某个公共接口读取数据块的流。数据在内部从底层源进入流,然后由消费者(consumer)进行处理。
  • 可写流,可以通过某个公共接口写入数据块的流。生产者(producer)将数据写入流,数据在内部传入底层数据槽(sink)。
  • 转换流, 由两种流组成,可写流用于接收数据(可写端),可读流用于输出数据(可读端)。这两个流之间是转换程序(transformer),可以根据需要检查和修改流内容。

流的基本单位是块(chunk)。块可是任意数据类型,但通常是定型数组。
所有流都会为已进入流但尚未离开流的块提供一个内部队列
如果块入列速度快于出列速度,则内部队列会不断增大。流不能允许其内部队列无限增大,因此它会使用反压(backpressure)通知流入口停止发送数据,直到队列大小降到某个既定的阈值之下。这个阈值由排列策略决定,这个策略定义了内部队列可以占用的最大内存,即高水位线(high water mark)

3.2 可读流

ReadableStreamDefaultController
生成器的值可以通过可读流的控制器传入可读流。访问这个控制器最简单的方式就是创建ReadableStream 的一个实例,并在这个构造函数的 underlyingSource 参数(第一个参数)中定义start()方法,然后在这个方法中使用作为参数传入的 controller。默认情况下,这个控制器参数是ReadableStreamDefaultController 的一个实例。调用控制器的 enqueue()方法可以把值传入控制器。所有值都传完之后,调用 close()关闭流。

async function* ints() {
 // 每 1000 毫秒生成一个递增的整数
 for (let i = 0; i < 5; ++i) {
 	yield await new Promise((resolve) => setTimeout(resolve, 1000, i));
 }
}
const readableStream = new ReadableStream({
	 async start(controller) {
		 for await (let chunk of ints()) {
		 controller.enqueue(chunk);
	 }
 	controller.close();
 }
});

ReadableStreamDefaultReader
ReadableStreamDefaultReader 实例可以通过流的 getReader()方法获取,调用这个方法会获得流的锁,保证只有这个读取器可以从流中读取值,消费者使用这个读取器实例的 read()方法可以读出值

3.3 可写流

创建 WritableStream

在传给 WritableStream 构造函数 underlyingSink参数中,通过实现 write()方法可以获得写入的数据:

const readableStream = new ReadableStream({
 write(value) {
 	console.log(value);
 }
}); 

要把获得的数据写入流,可以通过流的 getWriter()方法获取WritableStreamDefaultWriter的实例。这样会获得流的锁,确保只有一个写入器可以向流中写入数据

3.4 转换流

转换流用于组合可读流和可写流。数据块在两个流之间的转换是通过 transform()方法完成的

async function* ints() {
 // 每 1000 毫秒生成一个递增的整数
 for (let i = 0; i < 5; ++i) {
 	yield await new Promise((resolve) => setTimeout(resolve, 1000, i));
 }
}
const { writable, readable } = new TransformStream({
 transform(chunk, controller) {
 	controller.enqueue(chunk * 2);
 }
}); 

3.5通过管道连接流

最常见的用例是使用 pipeThrough()方法把ReadableStream接入TransformStream。从内部看,ReadableStream 先把自己的值传给TransformStream 内部的WritableStream,然后执行转换,接着转换后的值又在新的 ReadableStream 上出现。

4 .计时API

Performance 接口通过 JavaScript API 暴露了浏览器内部的度量指标,允许开发者直接访问这些信息并基于这些信息实现自己想要的功能。这个接口暴露在window.performance 对象上。

  • High Resolution Time API
  • Performance Timeline API
  • Navigation Timing API
  • User Timing API
  • Resource Timing API
  • Paint Timing API

4.1 High Resolution Time API

High Resolution Time API 定义了window.performance.now(),这个方法返回一个微秒精度的浮点值。
performance.now()计时器采用相对度量。这个计时器在执行上下文创建时从 0 开始计时
performance.timeOrigin 属性返回计时器初始化时全局系统时钟的值。

4.2 Performance Timeline API

Performance Timeline API 使用一套用于度量客户端延迟的工具扩展了 Performance 接口。性能度量将会采用计算结束与开始时间差的形式。这些开始和结束时间会被记录为 DOMHighResTimeStamp值,而封装这个时间戳的对象是 PerformanceEntry 的实例。
浏览器会自动记录各种 PerformanceEntry 对象,而使用 performance.mark()也可以记录自定义的 PerformanceEntry 对象。在一个执行上下文中被记录的所有性能条目可以通过 performance.getEntries()获取。
这个返回的集合代表浏览器的性能时间线(performance timeline)。每个PerformanceEntry 对象都有 nameentryTypestartTime duration属性

  • User Timing API,用于记录和分析自定义性能条目
  • Navigation Timing API, 提供了高精度时间戳,用于度量当前页面加载速度。
  • Resource Timing API, 提供了高精度时间戳,用于度量当前页面加载时请求资源的速度

5. Web 组件

一套用于增强 DOM 行为的工具,包括影子 DOM自定义元素HTML 模板.

5.1 HTML模板

提前在页面中写出特殊标记,让浏览器自动将其解析为 DOM 子树,但跳过渲染。这正是 HTML 模板的核心思想,而