Appearance
目录
核心思想
JavaScript 本质上是单线程的,这意味着所有任务(UI 渲染、用户交互、JS 代码执行)都在同一个主线程上排队执行。如果一个任务耗时过长,整个页面就会被"冻结",无法响应用户操作,造成卡顿。为了解决这个问题,浏览器引入了 "Workers",允许我们在后台创建新的线程来执行脚本,从而解放主线程。Web Worker 和 Service Worker 就是这套机制下的两种核心角色,但它们的分工和使命截然不同。
角色一:Web Worker - 主线程的"分身术"
主线程是一位分身乏术的火影忍者,他既要接待村民(响应用户交互),又要维护村容村貌(渲染 UI)。现在,他接到了一个需要耗费大量查克拉去完成的S级任务(复杂的计算)。如果他亲力亲为,那么在他完成任务期间,整个村子将无人管理,陷入停滞。
Web Worker 就是他的"分身术"(影分身)。主线程可以创造一个或多个分身(Web Worker 线程),把这个S级任务交给他。
- 分身在一个完全独立的地方埋头计算,不打扰本体。
- 本体则继续轻松地处理日常事务,确保村子(页面)的流畅运行。
- 当分身完成任务后,通过"飞鸽传书"(postMessage API)将结果告诉本体。
1. 核心职责与应用场景
- 职责:分担主线程的计算压力。专门处理那些 CPU 密集型或高延迟的任务,防止主线程被阻塞。
- 应用场景:
- 大量数据处理:解析巨大的 JSON 文件、处理大规模数据。
- 复杂计算:图像/视频处理(滤镜、算法分析)、数据加密/解密、复杂的数学运算。
- 实时数据预处理:在接收到大量 WebSocket 数据后,先在 Worker 中进行整理和计算,再将结果发送给主线程用于渲染。
2. 关键特性
- 生命周期与页面绑定:Web Worker 随页面的创建而创建,随页面的关闭而销毁。它完全附属于创建它的页面。
- 无法操作 UI:分身无法直接去修缮村子的房屋,即 Web Worker 不能访问 window、document 等 DOM API。它活在一个隔离的环境里。
- 通信方式:通过 postMessage() 发送消息,通过 onmessage 事件接收消息,以此与主线程进行通信。
角色二:Service Worker - 浏览器的"智能网络代理"
如果说 Web Worker 是为了解决"内部计算压力",那么 Service Worker 就是为了解决"外部网络依赖"。它不是一个简单的计算分身,而是一个更高阶的存在,扮演着 浏览器、应用与网络之间的"代理服务器"。
它就是一个存在你的应用和互联网之间的智能管家。所有从应用发出的网络请求,都会先经过他手。
- 当网络正常时:他会忠实地去网络上取回资源,并顺手将一些重要资源(如 CSS、JS、图片)缓存在自己的小仓库里。
- 当网络断开时:用户再次请求资源,虽然无法连接互联网,但这位管家会说:"别担心,上次你要的东西我都给你存着呢",然后直接从自己的仓库里把资源返回给应用。这就实现了离线访问。
- 超越页面:这位管家是独立于任何页面的。即使你关闭了应用的所有页面,他依然在后台待命,可以接收来自服务器的推送通知,或者在后台执行数据同步。
1. 核心职责与应用场景
- 职责:拦截和处理网络请求,充当网络代理。它是实现渐进式网络应用(PWA)的基石。
- 应用场景:
- 离线缓存:缓存应用的"外壳"和核心资源,让应用在离线时也能瞬时加载和使用。
- 消息推送:即使浏览器关闭,也能接收并向用户显示来自服务器的推送消息。
- 后台同步:在网络不佳时,允许用户提交表单,等网络恢复后,Service Worker 会在后台自动完成发送。
- 网络请求劫持:可以自定义网络请求的返回内容,例如根据不同条件返回不同的缓存版本,或者直接在 Service Worker 中生成响应。
2. 关键特性
- 独立生命周期:Service Worker 的生命周期与页面完全分离。它需要经历安装、激活等阶段,并且可以活在浏览器后台,不受页面关闭的影响。
- 强大的代理能力:可以拦截作用域范围内的所有 fetch 事件。
- 无法操作 UI:和 Web Worker 一样,它也不能直接访问 DOM。
- 安全性要求:必须运行在 HTTPS 协议下,以防止中间人攻击。