javascript基础学习系列三百二十七: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”
 流出口处理数据的速度比入口提供数据的速度快。流出口经常空闲(可能意味着流入口效率较 26 低),但只会浪费一点内存或计算资源,因此这种流的不平衡是可以接受的。
 流入和流出均衡。这是理想状态。
 流入口提供数据的速度比出口处理数据的速度快。这种流不平衡是固有的问题。此时一定会在
某个地方出现数据积压,流必须相应做出处理。 流不平衡是常见问题,但流也提供了解决这个问题的工具。所有流都会为已进入流但尚未离开流的

 大块数据可能不会一次性都可用。网络请求的响应就是一个典型的例子。网络负载是以连续信 息包形式交付的,而流式处理可以让应用在数据一到达就能使用,而不必等到所有数据都加载 完毕。
 大块数据可能需要分小部分处理。视频处理、数据压缩、图像编码和 JSON 解析都是可以分成小 部分进行处理,而不必等到所有数据都在内存中时再处理的例子。
第 24 章在讨论网络请求和远程资源时会介绍 Streams API 在 fetch()中的应用,不过 Streams API 本身是通用的。实现 Observable 接口的 JavaScript 库共享了很多流的基础概念。
提到流,可以把数据想像成某种通过管道输送的液体。JavaScript 中的流借用了管道相关的概念, 因为原理是相通的。根据规范,“这些 API 实际是为映射低级 I/O 原语而设计,包括适当时候对字节流 的规范化”。Stream API 直接解决的问题是处理网络请求和读写磁盘。
Stream API 定义了三种流。
 可读流:可以通过某个公共接口读取数据块的流。数据在内部从底层源进入流,然后由消费者
(consumer)进行处理。
 可写流:可以通过某个公共接口写入数据块的流。生产者(producer)将数据写入流,数据在内
部传入底层数据槽(sink)。
 转换流:由两种流组成,可写流用于接收数据(可写端),可读流用于输出数据(可读端)。这
两个流之间是转换程序(transformer),可以根据需要检查和修改流内容。
块、内部队列和反压

Streams API

Streams API 是为了解决一个简单但又基础的问题而生的:Web 应用如何消费有序的小信 息块而不是大块信息?这种能力主要有两种应用场景。
视频讲解
注意 虽然FetchAPI已经得到所有主流浏览器支持,但StreamsAPI则没有那么快得到支持。 20.9.1 理解流
流的基本单位是块(chunk)。块可是任意数据类型,但通常是定型数组。每个块都是离散的流片段, 可以作为一个整体来处理。更重要的是,块不是固定大小的,也不一定按固定间隔到达。在理想的流当 中,块的大小通常近似相同,到达间隔也近似相等。不过好的流实现需要考虑边界情况。
前面提到的各种类型的流都有入口和出口的概念。有时候,由于数据进出速率不同,可能会出现不 匹配的情况。为此流平衡可能出现如下三种情形。

块提供一个内部队列。对于均衡流,这个内部队列中会有零个或少量排队的块,因为流出口块出列的速度与流入口块入列的速度近似相等。这种流的内部队列所占用的内存相对比较小。 如果块入列速度快于出列速度,则内部队列会不断增大。流不能允许其内部队列无限增大,因此它 会使用反压(backpressure)通知流入口停止发送数据,直到队列大小降到某个既定的阈值之下。这个阈
值由排列策略决定,这个策略定义了内部队列可以占用的最大内存,即高水位线(high water mark)。 20.9.2 可读流
可读流是对底层数据源的封装。底层数据源可以将数据填充到流中,允许消费者通过流的公共接口 读取数据。

1. ReadableStreamDefaultController 来看下面的生成器,它每 1000 毫秒就会生成一个递增的整数:

async function* ints() {
// 每 1000 毫秒生成一个递增的整数 for (let i = 0; i < 5; ++i) {
yield await new Promise((resolve) => setTimeout(resolve, 1000, i)); }
}

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

   const readableStream = new ReadableStream({
      start(controller) {
console.log(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();
} });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值