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

沭阳县盛通园林绿化工程有限公司 2026/09/09 19:14:58

本文对比了服务工作者线程(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. 实际影响:是否立即生效直接影响用户体验和代码执行逻辑

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

河南网站建设烟台网站建设

项目场景:oracle导入数据,sys_user表数据错误问题描述原因分析:熊小二 使用oracle客户端工具,导入数据,导入成功

2026/06/30 11:43:28

网站建设论文汕头网站建设

35岁基层程序员分享AI时代成长心得:坚持做正确之事会迎来几何倍数拐点。核心策略包括:培养学习如何学习的能力;掌握AIGC工具提升效率;构建投资

2026/06/30 12:57:03

建设局网站网站建设模板

Linux文件权限、所有权管理及文件操作指南1. 文件权限与所有权管理在Linux系统中,对文件和目录的权限及所有权进行管理是系统管理的重要部分。1.1 递归更改权限和所有权如果要更改一个目录及其下所

2026/06/30 12:00:29

网站建设教程开县网站建设

你是否曾经遇到过这样的困境:阅读外文资料时,满屏的陌生文字让你无从下手?观看外语视频时,精彩内容因为语言障碍而变得索然无味?或者在

2026/06/30 10:43:21

网站建设软件宝安网站建设

Dxf-Parser:JavaScript实现的DXF文件解析解决方案【免费下载链接】dxf-parserA javascript parser for DXF files. It re

2026/06/30 12:50:33

律师网站建设长沙网站建设公司

企业数字化转型案例:MGeo助力集团数据资产沉淀在大型企业集团的数字化转型进程中,数据孤岛和实体不一致是长期困扰数据治理的核心难题。尤其是在涉及地理信息、门店管理、物流配送

2026/06/30 11:36:56

九江网站建设郑州建设网站

Gemma 3 270M量化版:轻量AI文本生成新选择【免费下载链接】gemma-3-270m-bnb-4bit项目地址: https://ai.gitcode.com/hf_mirro

2026/06/30 13:12:04

桂林网站建设青岛网站建设哪家好

Vivado仿真中信号延迟处理的实战指南:从原理到避坑在FPGA设计的世界里,功能正确只是第一步。真正考验工程师功力的地方,在于时序是否稳健、延迟是否可控。你

2026/06/30 11:13:54

网站建设全包网站建设 流程

想要为《艾尔登法环》添加全新武器系统?或者重新设计《黑暗之魂3》的Boss战斗机制?Mod Engine 2作为专业的魂系游戏模组工具,让每个玩家都能成为游戏

2026/06/30 11:02:53