Service Worker -- 特殊的Web Worker

Service Worker作为Web应用程序与浏览器间的代理服务器,实现离线缓存和后台消息传递。它不访问DOM,而是通过异步API工作,并在离线时仍能运行。Service Worker的生命周期包括安装、激活、等待和销毁四个阶段,主要用于网络资源代理和离线缓存。在使用中,可以拦截请求、缓存资源,是PWA(渐进式网页应用)的重要组成部分。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在介绍service之前,先引入一下PWA(由Google的Chrome团队创造),技术支持主要是ServiceWorker和Web App Mainfest

PWA是一种webapp模型,是一种渐进的web app,利用一些web特性,配合ui使用,增强web app的用户体验。(手机使用Safari 进入 m.weibo.cn/beta 将它保存在手机桌面上,点击桌面上相应快捷方式时,不会再显示url)。

那么刚才已经说过了,PWA有一个特性 -- 浏览器离线和弱网络环境可以急速访问。 这就使用了即将介绍的Service Worker:

功能:

它是充当在web应用程序与浏览器之间的代理服务器。离线缓存


特性:
后台消息传递

网络代理、转发请求、伪造响应

离线缓存

消息推送

现阶段来看,serviceWorker的功能主要集中在网络资源代理和离线缓存上。可以理解为他是一个在浏览器离线时,仍能运行的web wokrer。因此,window以及dom都是不能访问的。可以利用self访问全局上下文。

service worker 完全异步、同步API (XHR、LocalStroage)不能在其中使用。

正常情况下他是需要https环境才能跑起来的。但是本地服务器(127.0.0.1 / localhost)是可以使用的。

打开终端

重启apache:sudo /usr/sbin/apachectl restart

关闭apache:sudo /usr/sbin/apachectl stop

开启apache:sudo /usr/sbin/apachectl start

他的生命周期如下:共包含四个状态:安装、激活、等待、销毁(解雇)

                                              

在缓存的时候。我主要使用了cache ,cache和cacheStroage都是Service Worker API下的接口, 那么他们的区别是什么呢?

cacheStroage 主要保存了每个service worker 声明的cache对象。

举个例子理解一下:cacheStroage 是一个管理着所有cache的库

                                cache 是单个缓存库

 

可以直接使用全局的caches属性访问cacheStroage

cacheStroage主要有open 、match、has、delete、keys五个核心方法。可以对cache的不同匹配进行不同响应。注意:上面这五种方法都返回一个promise对象

跑题了...

接下来说一下 service worker 的使用

首先。可以在控制台 - > application -> service worker 进行一些对于service worker 的操作(update,delete等)

https://lavas-project.github.io/pwa-book/chapter04/4-service-worker-debug.html

下面讲一下它的具体使用:

// 基本的项目结构如下

界面如下:

// 首先在serviceworker.html 文件中对他进行注册和 一些请求的发送(为了后面截取请求)

if (navigator.serviceWorker != null) {
      // 使用浏览器特定方法注册一个新的service worker   返回值是promise对象
      navigator.serviceWorker.register('sw.js')
      .then(function(registration) {
        window.registration = registration;
        console.log('Registered events at scope: ', registration.scope);
      });
    }

    fetch("./data.json")
    fetch("./offline.json").then((res)=>{
      console.log("offlinetest");
    })
     var statusEl = document.querySelector("#network-status");
     // js监测在线离线状态
     if(!navigator.onLine){
       // 返回元素类名
       statusEl.classList = ["is-offline"];
       statusEl.innerText = 'offline';
     }

// 具体sw.js(service worker)文件如下:
里面写了一些日志信息。

共分4部分 
part 1:

1. 设置cache关键字(唯一标识)

2. cachelist  需要缓存的资源

console.log("service Test");

var cacheStorageKey = 'minimal-pwa-3';

var cacheList = [
  '/',
  "serviceworker.html",
  "index.css",
  "serviceworker.png",
  "data.json"
]

part 2:开始执行生命周期

1. sw内部触发  install事件

2. 打开一个缓存空间 将list 添加进去

3. 如果所有文件都缓存成功,则service worker 将被安装。如果任何文件无法下载和缓存,则安装步骤将失败。service worker 将不会激活(即不会被安装)

// 当浏览器解析完sw文件时,serviceworker内部触发install事件
// 仅触发一次
self.addEventListener('install', function(e) {
    // debugger;
    console.log('Cache event!')
    // 打开一个缓存空间,将相关需要缓存的资源添加到缓存里面
    e.waitUntil(
      caches.open(cacheStorageKey).then(function(cache) {
        console.log('Adding to Cache:', cacheList)
        return cache.addAll(cacheList)
      }).then(function() {
        console.log('install event open cache ' + cacheStorageKey);
        console.log('Skip waiting!')
        return self.skipWaiting();
      })
    )
  })
  

 

part 3:

1. sw内部触发  active事件

2. 通常进行一些过期资源释放的处理

  // 如果当前浏览器没有激活的service worker或者已经激活的worker被解雇
  self.addEventListener('activate', function(e) {
    debugger;
    console.log('Activate event');
    console.log('Promise all', Promise, Promise.all);
    // active事件中通常做一些过期资源释放的工作
    var cacheDeletePromises = caches.keys().then(cacheNames => {
      console.log('cacheNames', cacheNames, cacheNames.map);
      return Promise.all(cacheNames.map(name => {
        if (name !== cacheStorageKey) { // 如果资源的key与当前需要缓存的key不同则释放资源
          console.log('caches.delete', caches.delete);
          var deletePromise = caches.delete(name);
          console.log('cache delete result: ', deletePromise);
          return deletePromise;
        } else {
          return Promise.resolve();
        }
      }));
    });
  
    console.log('cacheDeletePromises: ', cacheDeletePromises);
    e.waitUntil(
      Promise.all([cacheDeletePromises]
      ).then(() => {
        console.log('activate event ' + cacheStorageKey);
        console.log('Clients claims.')
        return self.clients.claim();
      })
    )
  })

 

part 4:

1. 请求的拦截 、转发 、资源缓存等

这里主要体现了资源缓存的部分:(可以考虑动态将资源缓存下来--利用cache.put)

// 拦截网络请求 
  self.addEventListener('fetch', function(e) {
    console.log('Fetch event ' + cacheStorageKey + ' :', e.request.url);
    e.respondWith( // 首先判断缓存当中是否已有相同资源
      caches.match(e.request).then(function(response) {
        if (response != null) { // 如果缓存中已有资源则直接使用
          // 否则使用fetch API请求新的资源
          console.log('Using cache for:', e.request.url)
          return response
        }
        console.log('Fallback to fetch:', e.request.url)
        return fetch(e.request.url)
        // 动态缓存部分

        
      })
    )
  })

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值