网站建设与维护黄石网站建设

杭州车酷智能技术有限公司 2026/09/09 19:29:08

本文对比了服务工作者线程(Service Worker)生命周期中的关键事件和属性,包括注册、安装、激活和控制各阶段。


通过详细表格展示了不同事件的触发时机、监听位置(主线程/服务线程)和典型用途,并重点分析了事件是否立即生效的特性差异。


文章还提供了实际代码示例,说明如何正确处理异步操作(如waitUntil和respondWith),确保服务工作者线程生命周期管理的可靠性。


最后总结了不同生效时机的适用场景,帮助开发者优化离线应用的用户体验和功能实现。


服务工作者线程生命周期事件/属性对比表

阶段事件/属性监听位置触发时机典型用途
注册阶段navigator.serviceWorker.register()主线程注册服务工作者脚本首次注册或更新SW
registration对象主线程注册成功后返回管理SW更新、订阅等
安装阶段install事件服务线程SW脚本首次下载或检测到更新时预缓存资源、初始化DB
registration.installing主线程安装过程中可用检查安装状态
等待阶段registration.waiting主线程安装完成等待激活提示用户更新、跳过等待
激活阶段activate事件服务线程SW激活成功,获得控制权清理旧缓存、数据迁移
registration.active主线程SW已激活检查激活状态
控制阶段controllerchange事件主线程页面被新的SW控制时更新UI、重新加载页面
navigator.serviceWorker.controller主线程当前控制页面的SW检查当前控制器
更新检查updatefound事件主线程检测到新版本SW开始安装显示更新提示
registration.update()主线程手动触发更新检查强制检查更新
就绪状态navigator.serviceWorker.ready主线程SW已激活并准备就绪确保SW可用后执行操作
功能事件fetch事件服务线程发起网络请求时拦截和处理请求
push事件服务线程收到推送消息时显示推送通知
sync事件服务线程后台同步触发时同步离线数据
错误处理statechange事件主线程SW状态变化时调试状态变化
error事件主线程SW脚本加载失败时错误处理和降级

详细说明与示例代码

主线程监听的事件

// 注册服务工作者 const registration = await navigator.serviceWorker.register('/sw.js'); // 监听控制器变化 navigator.serviceWorker.addEventListener('controllerchange', () => { console.log('页面已被新的服务工作者控制'); }); // 监听更新发现 registration.addEventListener('updatefound', () => { console.log('发现新版本服务工作者'); }); // 检查等待中的SW if (registration.waiting) { // 提示用户更新 }

服务线程内监听的事件

// sw.js 文件内 // 安装事件 self.addEventListener('install', event => { event.waitUntil( caches.open('v1').then(cache => cache.addAll(['/app.css'])) ); }); // 激活事件 self.addEventListener('activate', event => { event.waitUntil( caches.keys().then(keys => Promise.all(keys.map(key => caches.delete(key))) ) ); }); // 拦截请求 self.addEventListener('fetch', event => { event.respondWith( caches.match(event.request).then(response => response || fetch(event.request) ) ); });

生命周期流程图

主线程 服务线程 │ │ ├─ register('sw.js') ──────────────────────▶│ │ │ │ 返回 registration 对象 │ │ │ │─监听 updatefound ────检测到更新───────────▶│ │ │ │ ├─ install 事件 │ │ (预缓存资源) │ │ │ registration.waiting 变为真 │ │ │ │─调用 skipWaiting() ───跳过等待───────────▶│ │ │ │ ├─ activate 事件 │ │ (清理旧缓存) │ │ │─监听 controllerchange ◀─获得控制权───────▶│ │ (页面被新SW控制) │ │ │ │─navigator.serviceWorker.ready───────────▶│ │ (SW准备就绪) │ │ │ └─监听 fetch/push/sync 等事件◄─处理事件─────▶│

重要区别总结

  1. 位置不同

    • 主线程:管理SW注册、更新和状态监控

    • 服务线程:处理具体功能逻辑(缓存、推送等)

  2. 时机不同

    • 主线程事件关注SW与页面的关系变化

    • 服务线程事件关注SW自身状态和功能执行

  3. 控制权不同

    • 主线程可以主动触发更新、跳过等待

    • 服务线程控制资源缓存和请求处理


服务工作者线程事件对比表

事件名称触发时机主要用途是否立即生效典型场景
controllerchangenavigator.serviceWorker.controller发生变化时触发检测页面是否被新的服务工作者控制立即生效页面刷新后检测是否由新SW控制,更新UI状态
updatefound当正在安装的服务工作者开始安装时触发(检测到新版本)提示用户有更新可用,可显示更新提示尚未生效检测到新版本SW,显示“有更新可用”提示
activate当服务工作者激活成功,获得控制权时触发清理旧缓存、迁移数据等准备工作已生效但尚未控制页面删除旧缓存,为控制客户端做准备

详细说明:


controllerchange

  • 触发条件navigator.serviceWorker.controller属性值改变

  • 特点:表明页面已被新的服务工作者控制

  • 示例使用

navigator.serviceWorker.addEventListener('controllerchange', () => { console.log('当前页面已被新的服务工作者控制'); });

updatefound

  • 触发条件:检测到新的服务工作者脚本并开始安装

  • 特点:仅表示发现新版本,不代表已激活

  • 示例使用

registration.addEventListener('updatefound', () => { console.log('发现新版本服务工作者'); });

activate

  • 触发条件:服务工作者成功激活,获得控制权

  • 特点:这是清理旧资源的理想时机(但还不能控制现有客户端)

  • 示例使用

self.addEventListener('activate', event => { // 清理旧缓存 event.waitUntil(caches.delete('old-cache')); });

生命周期顺序

  1. 检测到新版本 →updatefound事件

  2. 安装完成后等待激活 → (无特定事件)

  3. 激活成功 →activate事件(服务工作者已就绪)

  4. 控制页面 →controllerchange事件(页面已被控制)


重要区别

  • updatefoundactivate在服务工作者线程内监听

  • controllerchange在客户端页面(主线程)中监听

  • updatefound表示"发现更新",activate表示"准备就绪",controllerchange表示"已接管控制"


服务工作者线程生命周期事件/属性对比表(新增“是否立即生效”列)

阶段事件/属性监听位置是否立即生效触发时机典型用途
注册阶段navigator.serviceWorker.register()主线程否(异步)注册服务工作者脚本首次注册或更新SW
registration对象主线程立即注册成功后返回管理SW更新、订阅等
安装阶段install事件服务线程是,但需等待waitUntil()SW脚本首次下载或检测到更新时预缓存资源、初始化DB
registration.installing主线程立即安装过程中可用检查安装状态
等待阶段registration.waiting主线程立即安装完成等待激活提示用户更新、跳过等待
激活阶段activate事件服务线程是,但需等待waitUntil()SW激活成功,获得控制权清理旧缓存、数据迁移
registration.active主线程立即SW已激活检查激活状态
控制阶段controllerchange事件主线程立即页面被新的SW控制时更新UI、重新加载页面
navigator.serviceWorker.controller主线程立即当前控制页面的SW检查当前控制器
更新检查updatefound事件主线程立即检测到新版本SW开始安装显示更新提示
registration.update()主线程否(异步)手动触发更新检查强制检查更新
就绪状态navigator.serviceWorker.ready主线程否(Promise)SW已激活并准备就绪确保SW可用后执行操作
功能事件fetch事件服务线程是,但需等待respondWith()发起网络请求时拦截和处理请求
push事件服务线程是,但需等待waitUntil()收到推送消息时显示推送通知
sync事件服务线程是,但需等待waitUntil()后台同步触发时同步离线数据
错误处理statechange事件主线程立即SW状态变化时调试状态变化
error事件主线程立即SW脚本加载失败时错误处理和降级

"是否立即生效" 详细解释

立即生效的情况

// 示例1: 立即生效的属性 if (registration.waiting) { // 立即返回true/false // 已有等待中的SW } // 示例2: 立即触发的事件 navigator.serviceWorker.addEventListener('controllerchange', () => { // 事件触发后立即执行 window.location.reload(); // 可以立即重新加载页面 });

需等待 Promise 的情况

// 示例1: 异步操作 navigator.serviceWorker.ready.then(() => { // 只有SW完全就绪后才会执行 console.log('SW准备就绪'); }); // 示例2: 需要 waitUntil() 的事件 self.addEventListener('install', event => { // 必须等待缓存操作完成 event.waitUntil( caches.open('v1').then(cache => { return cache.addAll(['/app.js', '/style.css']); // 异步操作 }) ); // 只有在Promise完成后,install才完成 });

需等待 respondWith() 的情况

self.addEventListener('fetch', event => { // 必须调用 respondWith() 并提供Promise event.respondWith( caches.match(event.request).then(response => { // 这个Promise完成前,页面请求不会得到响应 return response || fetch(event.request); }) ); });

不同生效时机的使用场景

立即生效用户界面响应

// 立即更新UI状态 registration.addEventListener('updatefound', () => { // 立即显示更新提示 showUpdateToast('发现新版本,正在下载...'); });

需等待 Promise确保操作完成

// 确保SW激活后再发送消息 navigator.serviceWorker.ready.then(registration => { registration.active.postMessage('SW已就绪,开始工作'); });

需 waitUntil保证生命周期完整性

self.addEventListener('activate', event => { // 保证清理完成前,SW不会进入下一步 event.waitUntil( caches.keys().then(cacheNames => { return Promise.all( cacheNames.map(cacheName => { if (cacheName !== 'current-v2') { return caches.delete(cacheName); // 删除旧缓存 } }) ); }) ); });

关键要点总结

  1. 立即生效:主要用于状态查询和UI更新,不涉及异步操作

  2. 等待 Promise:用于确保操作顺序,避免竞态条件

  3. waitUntil/respondWith:服务线程生命周期管理的关键机制,保证异步操作完成

  4. 实际影响:是否立即生效直接影响用户体验和代码执行逻辑

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

高端品牌网站建设湖南网站建设

Linux 文件压缩与归档操作指南在 Linux 系统中,文件的压缩与归档是日常操作中常见的需求。掌握不同的压缩和归档工具及其使用方法,能让我们更高效地管理文件。下面将详细介绍几种常用的工具及其操作。

2026/06/30 10:50:52

网站建设流程静安网站建设

单相MMC,单相MMC整流器,单相模块化多电平变换器,直流电压波动抑制,桥臂电压均衡控制,模块电压均衡控制,载波移相

2026/06/30 10:33:51

孝感网站建设网站建设素材

Arduino开发避坑指南:USB转串芯片驱动兼容性实战解析你有没有遇到过这样的情况?刚买回来一块Arduino Nano,兴冲冲打开IDE准备烧个“Blin

2026/06/30 14:09:09

品牌网站建设青岛网站建设哪家好

突破限制:一键解决Cursor Pro额度与机器码绑定难题【免费下载链接】cursor-free-everyday完全免费, 自动获取新账号,一键重置新额度, 解决机器码问题, 自动满额

2026/06/30 14:20:10

网站建设的知名网站建设

好的,我来为您介绍前缀索引的概念及其应用。1. 基本概念前缀索引(Prefix Index)是一种在数据库中仅对字段值的前缀部分建立索引的技术。例如ÿ

2026/06/30 11:03:53

唐山网站建设三亚网站建设

你是否曾经面对Android OTA更新包束手无策?那些神秘的payload.bin文件里到底隐藏着什么宝藏?今天,我将为你介绍一款能够快速解密这些数据的神奇

2026/06/30 13:54:08

郑州网站建设网站建设一条龙

VFXToolbox终极指南:5大功能亮点彻底改变特效制作流程【免费下载链接】VFXToolboxAdditional tools for Visual Effect Artists项目

2026/06/30 11:05:23

网站建设技术龙岗网站建设公司

还在为图片中的文字识别而烦恼吗?无论是截图中的代码片段、PDF文档的批量处理,还是多语言文本的准确提取,Umi-OCR作为一款免费开源的离线OCR软件

2026/06/30 13:45:07

成都网站建设呼和浩特网站建设

博德之门3脚本扩展器的隐藏技巧:从玩家到创造者的进阶之路【免费下载链接】bg3seBaldur's Gate 3 Script Extender项目地址: https://git

2026/06/30 14:07:08