写在开篇
笔者之前一直不清楚 chrome.offscreen 的应用场景,直到看到了这篇文章后才有些许眉目。
所以今天呢,笔者打算跟着原文的思路,细细的整理下这个业务场景:当用户切换到某一些网站的 TAB 页时需要开启音频声音,而当切换到其他网址时则需要关闭音频声音;
技术方案对比
从 Content 层出发的方案
当 chrome.offscreen 还没有进入我的知识库时,应对这个需求场景,我的技术方案如下:利用插件为每个 TAB 页注入一个音频 DOM 节点,然后由 Service Worker 作为总控制者,在 TAB 页被激活时,向每个 Content 层发送消息去控制每个 Content 层中的音频的开关。
这个方案的流程图如下:

从上图中,你会看到每个 TAB 页都被注入了一个音频 DOM 节点(也就是一个浏览器中其实存在了N多个一模一样的音频)。
这种设计下,不得不防的有这样两种极端情况:
1. 因为音频有N多个,当 Service Worker 去控制开关时,如果 控制不得当 或者 出现Service Worker与Content层通信消息丢失问题 的话,那么就会出现多个音频同时处在打开状态的问题;
此时,你可能会问,那就不能 “只征用其中一个Content层的音频,其他音频都关着吗?”。答案是:也是一种方案吧,但这样的设计会更复杂一些、不像“音频的状态跟随 TAB 页的激活状态”来的通用;
我们可以设想一下,如果我们只征用其中一个 TAB 页的 Content 层,那一方面就要考虑使用音频的 TAB 页被关闭后,如何去切换可用 TAB 页的方案;另一方面需要开发者专门针对被选中的 TAB 页来写逻辑,笔者一般在做技术方案时,会尽量以普适性为基础去做设计,而不在特殊特征点下写逻辑;
2. 另一个极端、细致的场景就是:如果当前 TAB-1 的音频正打开着,现在用户切换到了 TAB-2,这个时候,Service Worker需要向 TAB-1 发送消息让它关闭音频,然后给 TAB-2 发送消息开启音频。在这个流程里,如果 TAB-2 的消息率先被接收到并执行的话,那么就会出现两个音频同时播放的情况;
理论上这种场景是存在的,因为 Service Worker 与多个 Content 层的通信消息传递是 并行的 且 单次消息传递的时间是不确定的。
以上两个问题带来的是用户侧极差的交互体验,而我们今天要细讲的 chrome.offscreen 方案 就完美的避开了它们。
利用 offscreen 的技术方案
首先,我们来看看 chrome.offcreen 协助下的技术方案流程图。

依据上图,我们可以看到几个点:
1. 整个浏览器下,同一时间,只有一个音频存在,即,要么开要么关,不会出现多音频问题(当然,代码里也要配合控制);
2. 虽然图上画了几个 TAB 页,但事实上所有监听处理、消息发送都只存在于 Service Worker 和 offscreen 之间。即,技术方案简单、清晰可靠;
接下来,结合代码,你会发现整个技术方案及落地真的 so easy~
1. 离屏文档中创建音频节点 & 接收消息开关音频:
2. 监听 TAB 页的激活、更新、关闭事件,相应的事件下,由 Service Worker 触发 offscreen 去开启、关闭音频。
写完代码,当然要贴一下本地运行的Demo啦~
写在最后
就像《源网站数据采集方案之解析DOM(五)》中的 chrome.scripting 为解析 DOM 数据提供了极大的便利一样,本节所阐述的 chrome.offscreen 也为多 Content 场景提供了公共组件的能力。虽然,我们今天只是讲了其中的一个应用场景,但事实上,offscreen 还有处理 iframe 、剪切板等的能力,未来,笔者会更努力的去发掘它们的应用场景并落实到文章中,请大家持续关注我的博客呀~


















