20.7 Notifications API
Notifications API用于向用户显示通知。
无论从哪个角度看,这里的通知都很类似alert()对话框:
都使用JavaScript API触发页面外部的浏览器行为,而且都允许页面处理用户与对话框或通知弹层的交互。
不过,通知提供更灵活的自定义能力。
20.7.1 通知权限
Notifications API有被滥用的可能,因此默认会开启两项安全措施:
❑ 通知只能在运行在安全上下文的代码中被触发;
❑ 通知必须按照每个源的原则明确得到用户允许。
除非用户没有明确给出允许或拒绝的答复,否则这个权限请求对每个域只会出现一次。浏览器会记住用户的选择,如果被拒绝则无法重来。
页面可用全局对象Notification向用户请求通知权限。
这个对象有一个requestPemission()方法,该方法返回一个期约,用户在授权对话框上执行操作后这个期约会解决。
Notification.requestPermission().then((permission) => {console.log('用户已响应权限请求', permission);});
“granted”值意味着用户明确授权了显示通知的权限。
除此之外的其他值,意味着显示通知会静默失败。
若用户拒绝授权,这个值就是”denied”。
一旦拒绝,就无法通过编程方式挽回,因为不可能再触发授权提示。
20.7.2 显示和隐藏通知
Notification构造函数用于创建和显示通知。
最简单的通知形式是只显示一个标题,这个标题内容可以作为第一个参数传给Notification构造函数。
20.7.3 通知生命周期
回调通知并非只用于显示文本字符串,也可用于实现交互。
Notifications API提供了4个用于添加回调的生命周期方法:
❑ onshow在通知显示时触发;
❑ onclick在通知被点击时触发;
❑ onclose在通知消失或通过close()关闭时触发;
❑ onerror在发生错误阻止通知显示时触发。
20.8 Page Visibility API
Web开发中一个常见的问题是:开发者不知道用户什么时候真正在使用页面。
如果页面被最小化或隐藏在其他标签页后面,那么轮询服务器或更新动画等功能可能就没有必要了。
Page Visibility API旨在为开发者提供页,面对用户是否可见的信息。
这个API本身非常简单,由3部分构成。
❑ document.visibilityState值,表示下面4种状态之一。
■ 页面在后台标签页或浏览器中最小化了。
■ 页面在前台标签页中。
■ 实际页面隐藏了,但对页面的预览是可见的(例如在Windows 7上,用户鼠标移到任务栏图标上会显示网页预览)。
■ 页面在屏外预渲染。
❑ visibilitychange事件,该事件会在文档从隐藏变可见(或反之)时触发。
❑ document.hidden布尔值,表示页面是否隐藏。这可能意味着页面在后台标签页或浏览器中被最小化了。这个值是为了向后兼容才继续被浏览器支持的,应该优先使用document.visibilityState检测页面可见性。
要想在页面从可见变为隐藏或从隐藏变为可见时得到通知,需要监听visibilitychange事件。document.visibilityState的值是以下三个字符串之一:
❑ “hidden”❑ “visible”❑ “prerender”
20.9 Streams API
Streams API是为了解决一个简单但又基础的问题而生的:Web应用如何消费有序的小信息块而不是大块信息?
这种能力主要有两种应用场景:
❑ 大块数据可能不会一次性都可用。网络请求的响应就是一个典型的例子。网络负载是以连续信息包形式交付的,而流式处理可以让应用在数据一到达就能使用,而不必等到所有数据都加载完毕。
❑ 大块数据可能需要分小部分处理。视频处理、数据压缩、图像编码和JSON解析都是可以分成小部分进行处理,而不必等到所有数据都在内存中时再处理的例子。
20.9.1 理解流
根据规范,“这些API实际是为映射低级I/O原语而设计,包括适当时候对字节流的规范化”。
Stream API直接解决的问题是:处理网络请求和读写磁盘。
Stream API定义了三种流。
❑ 可读流:可以通过某个公共接口读取数据块的流。数据在内部从底层源进入流,然后由消费者(consumer)进行处理。
❑ 可写流:可以通过某个公共接口写入数据块的流。生产者(producer)将数据写入流,数据在内部传入底层数据槽(sink)。
❑ 转换流:由两种流组成,可写流用于接收数据(可写端),可读流用于输出数据(可读端)。这两个流之间是转换程序(transformer),可以根据需要检查和修改流内容。
块、内部队列和反压
流的基本单位是块(chunk)。块可是任意数据类型,但通常是定型数组。每个块都是离散的流片段,可以作为一个整体来处理。更重要的是,块不是固定大小的,也不一定按固定间隔到达。
各种类型的流都有入口和出口的概念。
有时由于数据进出速率不同,可能会出现不匹配的情况。
为此流平衡可能出现如下三种情形:
❑ 流出口处理数据的速度比入口提供数据的速度快。流出口经常空闲(可能意味着流入口效率较低),但只会浪费一点内存或计算资源,因此这种流的不平衡是可以接受的。
❑ 流入和流出均衡。这是理想状态。
❑ 流入口提供数据的速度比出口处理数据的速度快。这种流不平衡是固有的问题。此时一定会在某个地方出现数据积压,流必须相应做出处理。
流不平衡是常见问题,但流也提供了解决这个问题的工具。
所有流都会为已进入流但尚未离开流的块提供一个内部队列。
如果块入列速度快于出列速度,则内部队列会不断增大。
流不能允许其内部队列无限增大,因此它会使用反压(backpressure)通知流入口停止发送数据,直到队列大小降到某个既定的阈值之下。
这个阈值由排列策略决定,这个策略定义了内部队列可以占用的最大内存,即高水位线(high watermark)。
20.9.2 可读流
可读流是对底层数据源的封装。底层数据源可以将数据填充到流中,允许消费者通过流的公共接口读取数据。
1.ReadableStreamDefaultController
2.ReadableStreamDefaultReader
20.9.3 可写流
可写流是底层数据槽的封装。底层数据槽处理通过流的公共接口写入的数据。
1.创建WritableStream
2.WritableStreamDefaultWriter
要把获得的数据写入流,可以通过流的getWriter()方法获取WritableStreamDefaultWriter的实例。这样会获得流的锁,确保只有一个写入器可以向流中写入数据
20.9.4 转换流
转换流用于组合可读流和可写流。数据块在两个流之间的转换是通过transform()方法完成的。
20.9.5 通过管道连接流
流可以通过管道连接成一串。
最常见的用例是使用pipeThrough()方法把ReadableStream接入TransformStream。
从内部看,ReadableStream先把自己的值传给TransformStream内部的WritableStream,然后执行转换,接着转换后的值又在新的ReadableStream上出现。
另外,使用pipeTo()方法也可以将ReadableStream连接到WritableStream。整个过程与使用pipeThrough()类似
20.10 计时API
页面性能始终是Web开发者关心的话题。
Performance接口通过JavaScriptAPI暴露了浏览器内部的度量指标,允许开发者直接访问这些信息,并基于这些信息实现自己想要的功能。
这个接口暴露在window.performance对象上。
所有与页面相关的指标,包括已经定义和将来会定义的,都会存在于这个对象上。
20.10.1 High Resolution Time API
Date.now()方法只适用于日期时间相关操作,而且是不要求计时精度的操作。
考虑如下duration会包含意外值的情况:
❑ duration是0。Date.now()只有毫秒级精度,如果foo()执行足够快,则两个时间戳的值会相等。
❑ duration是负值或极大值。如果在foo()执行时,系统时钟被向后或向前调整了(如切换到夏令时),则捕获的时间戳不会考虑这种情况,因此时间差中会包含这些调整。
为此,必须使用不同的计时API来精确且准确地度量时间的流逝。
HighResolution Time API定义了window.performance.now(),这个方法返回一个微秒精度的浮点值。
因此,使用这个方法先后捕获的时间戳更不可能出现相等的情况。而且这个方法可以保证时间戳单调增长。
20.10.2 Performance Timeline API
Performance Timeline API使用一套用于度量客户端延迟的工具扩展了Performance接口。
性能度量将会采用计算结束与开始时间差的形式。
这些开始和结束时间会被记录为DOMHighResTimeStamp值,而封装这个时间戳的对象是PerformanceEntry的实例。
1.User Timing API
User Timing API用于记录和分析自定义性能条目。
2.Navigation Timing API
Navigation Timing API提供了高精度时间戳,用于度量当前页面加载速度。
3.Resource Timing API
Resource Timing API提供了高精度时间戳,用于度量当前页面加载时请求资源的速度。
