[TOC]
疑问
第一次听说“工作者线程”,这是什么?
JavaScript的单线程可以保证它与不同浏览器API兼容。
- 如果支持多线程,那么像DOM这样的API就会出现问题。
- 工作者线程的价值
- 允许把主线程的工作转嫁给独立的实体,而不会改变现有的单线程模型。
- JavaScript环境实际上是运行在托管操作系统中的虚拟环境。(就是宿主环境)
- 在浏览器中每打开一个页面,就会分配一个它自己的环境。
- 每个页面都有自己的内存、事件循环、DOM,等等。
- 每个页面就相当于一个沙盒,不会干扰其他页面。
- 浏览器同时管理多个环境是非常简单的,因为所有这些环境都是并行执行的。
- 工作者线程
- 原始页面环境之外、完全独立的二级子环境。
- 能与依赖单线程交互的API(如DOM)互操作,但可以与父环境并行执行代码。
-
工作者线程类型
专用工作者线程
- 工作者线程、Web Worker或Worker
- 可以让脚本单独创建一个JavaScript线程,以执行委托的任务。
- 只能被创建它的页面使用。
- 在专用工作者线程内部,全局作用域是DedicatedWorkerGlobalScope的实例。
- 因为这继承自WorkerGlobalScope,所以包含它的所有属性和方法。
- 工作者线程可以通过self关键字访问该全局作用域。
- 共享工作者线程
- 类似专用工作者线程
- 可以被多个不同的上下文使用,包括不同的页面。
服务工作者线程
- 用途是拦截、重定向和修改页面发出的请求
-
专用工作者线程
在行内创建工作者线程
const blob = new Blob([ ` self.onmessage = ({ data, source }) => { console.log('service worker head:', data); source.postMessage('bar'); }; console.log(self, self.location); `, ]); const url = window.URL.createObjectURL(blob); const myWorker = new Worker(url);
服务工作者线程
涉及的内容极其广泛,几乎可以单独写一本书
- 就其职能来看,是十分有潜力的技术
- 比如批量修改请求的传参,或者批量修改接口返回的数据等等
- 核心是网络缓存,通常用于制作离线应用。
- 服务工作者线程应该也是通过self关键字访问全局作用域的。
-
生命周期
服务工作者线程可能存在的状态
- 已解析(parsed)
- 调用navigator.serviceWorker.register()会启动创建服务工作者线程实例的过程。
- 刚创建的服务工作者线程实例会进入已解析状态。
- 安装中(installing)
- 已安装(installed)
- 已安装状态是触发逻辑的好时机
- 检查方式:
- 激活中(activating)
- 已激活(activated)
- 已失效(redundant)
- 已解析(parsed)
状态的每次变化都会在ServiceWorker对象上触发statechange事件
服务工作者线程消息
拦截fetch事件
拦截能力不限于fetch()方法发送的请求
- 也能拦截对JavaScript、CSS、图片和HTML(包括对主HTML文档本身)等资源发送的请求。
- 这些请求可以来自JavaScript,也可以通过