Web Worker 和 Service Worker的区别及使用

Web Worker 和 Service Worker 都是浏览器提供的 JavaScript 多线程技术,但它们的用途和工作方式有显著区别。

对比项Web WorkerService Worker
用途用于在后台线程执行 CPU 密集型任务,避免阻塞主线程主要用于离线缓存、网络请求拦截、推送通知等 PWA(渐进式 Web 应用)功能
生命周期由页面创建,页面关闭后终止独立于页面,即使页面关闭也能运行(直到被浏览器终止)
DOM 访问❌ 不能访问 DOM❌ 不能访问 DOM
网络请求⚠️ 可以发起 fetch,但不能拦截请求✅ 可以拦截、修改网络请求(fetch 事件)
存储能力⚠️ 可使用 IndexedDBlocalStorage(同步 API 不可用)✅ 可使用 Cache APIIndexedDB
通信方式✅ postMessage 与主线程通信✅ 通过 postMessage 与页面通信,也支持 BroadcastChannel
典型应用场景大数据计算、图像处理、复杂算法离线缓存、资源预加载、后台同步、推送通知
注册方式new Worker('worker.js')navigator.serviceWorker.register('sw.js')
作用范围仅影响当前页面可控制多个页面(作用域内)
是否支持 importScripts✅ 支持✅ 支持

Web Worker(专用 Worker)

  • 用途:在独立线程运行脚本,防止主线程卡顿(如计算、数据处理)。

  • 特点

    • 由页面创建,页面关闭后 Worker 终止。

    • 不能访问 DOM、windowdocument

    • 通过 postMessage 与主线程通信。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        // 主线程 main.js
const worker = new Worker('./worker.js');

// 接收消息
worker.onmessage = function(e) {
    console.log('1111');
  console.log('收到Worker消息:', e.data);
};

// 发送消息
worker.postMessage('开始计算zzz');
    </script>
</body>
</html>

还需要执行的worker.js

// worker.js
self.onmessage = function(e) {
    console.log('收到主线程消息:', e.data);
    
    // 模拟耗时计算
    const result = heavyCalculation();
    
    // 发送结果
    self.postMessage(result);
  };
  
  function heavyCalculation() {
    // 复杂计算逻辑
    let sum = 0;
    for(let i = 0; i < 9999; i++) {
      sum += i;
    }
    return sum;
  }

Service Worker 实现PWA页面

  • 用途:充当网络代理,实现离线缓存、资源预加载、后台同步等 PWA 功能。

  • 特点

    • 独立于页面运行,即使页面关闭也能存活(用于后台同步、推送通知)。

    • 可以拦截 fetch 请求,返回缓存数据。

    • 必须通过 HTTPS(本地开发允许 localhost)。

 需要注意的是使用http-server -c-1启动服务需要使用这样的地址访问 http://127.0.0.1:8080/ 才能正常激活service worker

 目录结构

index.html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Service Worker 示例</title>
    <link rel="stylesheet" href="./styles/main.css">
</head>
<body>
    <h1>Service Worker 演示</h1>
    <img src="./images/logo.png" alt="Logo">
    <script src="./scripts/app.js"></script>
    <script>
        // 注册 Service Worker
        if ('serviceWorker' in navigator) {
            console.log('浏览器支持 Service Worker');
            // 直接执行注册代码
            navigator.serviceWorker.register('./sw.js')
               .then(registration => {
                    console.log('ServiceWorker 注册成功: ', registration.scope);
                })
               .catch(err => {
                    console.error('ServiceWorker 注册失败,错误信息:', err.message, '错误堆栈:', err.stack);
                });
        } else {
            console.log('浏览器不支持 Service Worker');
        }
    </script>
</body>
</html>
sw.js
const CACHE_NAME = 'my-site-cache-v1';
// 修改资源路径
const ASSETS_TO_CACHE = [
  './',
  './index.html', // 离线回退页面
  './styles/main.css',
  './scripts/app.js',
  './images/logo.png'
];

// 安装阶段 - 缓存静态资源
self.addEventListener('install', event => {
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(cache => {
        console.log('正在缓存核心资源');
        return cache.addAll(ASSETS_TO_CACHE);
      })
      .catch(err => {
        console.log('缓存失败: ', err);
      })
  );
})

// 激活阶段 - 清理旧缓存
self.addEventListener('activate', event => {
  event.waitUntil(
    caches.keys().then(cacheNames => {
      return Promise.all(
        cacheNames.map(cacheName => {
          if (cacheName !== CACHE_NAME) {
            console.log('删除旧缓存: ', cacheName);
            return caches.delete(cacheName);
          }
        })
      );
    })
  );
});

// 拦截请求 - 缓存优先策略
self.addEventListener('fetch', event => {
  event.respondWith(
    caches.match(event.request)
      .then(response => {
        // 命中缓存则返回,否则网络请求
        return response || fetch(event.request);
      })
  );
});

// 后台同步示例(需配合 SyncManager API)
self.addEventListener('sync', (event) => {
  if (event.tag === 'sync-data') {
    event.waitUntil(sendOfflineData());
  }
});

async function sendOfflineData() {
  // 在这里实现后台同步逻辑(如提交离线数据到服务器)
  console.log('后台同步执行...');
}
styles/main.css
.img {
    height: 100px;
    width: 100px;
}
 scripts/app.js
console.log('主应用脚本已加载1');

// 检查 Service Worker 更新
if ('serviceWorker' in navigator) {
  navigator.serviceWorker.ready.then(registration => {
    registration.addEventListener('updatefound', () => {
      const newWorker = registration.installing;
      console.log('发现新版本 Service Worker');
      
      newWorker.addEventListener('statechange', () => {
        if (newWorker.state === 'installed') {
          if (navigator.serviceWorker.controller) {
            console.log('新内容已下载,刷新页面即可使用');
            // 这里可以添加 UI 提示用户刷新
          } else {
            console.log('内容已缓存,可离线使用');
          }
        }
      });
    });
  });
}
 images/logo

关键功能说明

  1. 预缓存静态资源

    • 在 install 阶段缓存 ASSETS_TO_CACHE 列表中的文件(如 HTML、CSS、JS)。

  2. 动态缓存

    • 在 fetch 事件中,优先返回缓存,若无则请求网络并缓存响应。

  3. 离线回退

    • 当网络请求失败且请求的是 HTML 时,返回 fallback.html

  4. 缓存清理

    • 在 activate 阶段删除旧版本的缓存。

  5. 后台同步

    • 监听 sync 事件,在恢复网络后执行离线任务(需浏览器支持)。


 测试 Service Worker

  1. 首次加载

    • 打开页面,检查 DevTools → Application → Service Workers 是否注册成功。

    • 在 Cache Storage 中应看到缓存的静态资源。

  2. 离线测试

    • 关闭网络,刷新页面,静态资源应能正常加载。

  3. 更新 Service Worker

    • 修改 sw.js 或 CACHE_NAME 版本号,重新加载页面触发更新。


注意事项

  • HTTPS 要求:生产环境必须使用 HTTPS(本地开发可用 localhost)。

  • 缓存策略:根据业务需求调整缓存逻辑(如不缓存 API 请求)。

  • 作用域scope 决定 SW 控制的页面范围(如 /app/ 下的页面)。

通过这个示例,你可以快速实现一个支持离线访问的 PWA 应用

PWA(Progressive Web App,渐进式网页应用)

是一种结合网页和原生应用优势的技术,通过现代 Web 技术提供类似原生应用的体验。以下是它的核心特点和解释:


1. 核心特点

  • 可离线使用:通过 Service Worker 缓存资源,即使无网络也能访问。

  • 安装到桌面:用户可将网页添加到主屏幕,像独立应用一样启动(无需应用商店)。

  • 响应式设计:适配手机、平板、电脑等多种设备。

  • 推送通知:支持消息推送(类似原生 App)。

  • 安全性:必须运行在 HTTPS 环境下,确保数据安全。


2. 关键技术

  • Service Worker:后台运行的脚本,管理缓存和离线功能。

  • Web App Manifest:JSON 文件,定义应用名称、图标、启动样式等。

  • HTTPS:强制要求,保证安全性。

  • App Shell 架构:快速加载核心界面框架,提升性能。


3. 优势 vs 传统网页/原生应用

对比项PWA传统网页原生应用
安装方式浏览器添加到主屏幕仅浏览器访问应用商店下载
离线功能✅ 支持❌ 不支持✅ 支持
更新自动(Service Worker)实时刷新需应用商店审核
开发成本低(Web 技术)最低高(需多平台开发)

4. 典型应用场景

  • 电商(如 AliExpress、京东 Lite)

  • 社交媒体(Twitter Lite)

  • 新闻博客(内容型网站)

  • 工具类应用(计算器、天气预报)

总结

场景选择
需要后台计算(如大数据处理)Web Worker
需要离线缓存、拦截网络请求Service Worker
需要推送通知、后台同步Service Worker
需要多线程并行计算Web Worker 或 Shared Worker(跨页面通信)

两者可以结合使用,例如用 Web Worker 处理数据,用 Service Worker 缓存结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流氓也是种气质 _Cookie

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值