Service Worker的生命周期和全局对象和API

Service Worker的生命周期和全局对象和API

当我们注册了Service Worker后,它会经历生命周期的各个阶段,同时会触发相应的事件。整个生命周期包括了:installing --> installed --> activating --> activated --> redundant。当Service Worker安装(installed)完毕后,会触发install事件;而激活(activated)后,则会触发activate事件。
serviceWorker中,进程的全局对象(类似于window)叫做self,我们可以把生命周期监听挂载到这上面。

ExtendableEvent.waitUntil()

在说起self监听的各个事件之前,先介绍一下ExtendableEvent这个类,后续的很多返回事件都是继承了这个类的子类。
因此他们都可以使用ExtendableEvent.waitUntil()方法。

实际上,避免在sw中阻塞线程,sw提供的api基本都是异步,使用await / Promise去处理。
waitUntil接受一个Promise参数,可以保持长任务中线程的活性。
waitUntil方法解读

ExtendableEvent.waitUntil() 方法告诉事件分发器该事件仍在进行。这个方法也可以用于检测进行的任务是否成功。在服务工作线程中,这个方法告诉浏览器事件一直进行,直至 promise 解决,浏览器不应该在事件中的异步操作完成之前终止服务工作线程。
 
service worker 中的 install (en-US) 事件使用 waitUntil() 来将服务工作线程保持在 installing (en-US) 阶段。如果传入 waitUntil() 的 promise 被拒绝,则将此次安装视为失败,丢弃这个服务工作线程。这主要用于确保在服务工作线程安装以前,所有依赖的核心缓存都已经成功载入。
 
service worker 中的 activate (en-US) 事件使用 waitUntil() 来延迟函数事件,如 fetch 和 push,直至传入 waitUntil() 的 promise 被解决。这让服务工作线程有时间更新数据库架构(database schema)和删除过时缓存,让其他事件能在一个完成更新的状态下进行。
 
waitUntil() 方法最初必须在事件回调里调用,在此之后,方法可以被调用多次,直至所有传入的 promise 被解决。

register

service worker 的注册日志记录在 Chrome 浏览器中可以通过访问 chrome://serviceworker-internals 查看。
ServiceWorkerContainer.register()
如果成功,ServiceWorker会将scriptURL绑定到一个scope(页面路径上)。成功了会返回一个ServiceWorkerRegistration对象(下有介绍)。

ServiceWorkerContainer.register(scriptURL, options).then(
  function (ServiceWorkerRegistration) {
    // do something
  },
).catch(e=>{
});

参数

  • scriptURL service worker 脚本的 URL.
  • options 可选 注册时提供选项的配置对象。目前可用的选项包括:
    scope: 表示定义 service worker 注册范围的 URL;service worker 可以控制的 URL 范围。通常是相对 URL。默认值是基于当前的 location,并以此来解析传入的路径。

返回

返回一个 Promise 对象,值是 ServiceWorkerRegistration。

ServiceWorkerRegistration

在serviceWorker注册成功后,ServiceWorkerRegistration注册对象将挂载到sw线程全局对象上,使用self.registration就可以拿到注册对象了~
ServiceWorkerRegistration
它的原型是EventTarget对象,可以使用最基本的EventTarget.addEventListener()EventTarget.removeEventListener()EventTarget.dispatchEvent()

properties

  • active
    初始值为null,返回一个处于激活中或已激活状态的服务工作线程。如果客户端的URL位于注册的作用域内(在首次调用ServiceWorkerContainer.register时设置的scope选项),则一个活跃的工作线程会控制一个Client。
    在这里插入图片描述

  • installing
    返回一个处于安装状态的服务工作线程。这一开始被设置为null。
    安装完成之后,active会有值,installing的工作线程又回回到null。

  • pushManager
    返回对PushManager接口的引用,用于管理推送订阅,包括订阅、获取活跃订阅以及访问推送权限状态。
    一般用来注册webApp消息推送事件。

        var subscribeOptions = {
            userVisibleOnly: true,
            applicationServerKey: window.urlBase64ToUint8Array(publicKey)
        };  // 生成对应的pushSubscription数据,用于标识用户与安全验证
        
        registration.pushManager.subscribe(subscribeOptions).then(function (pushSubscription) {
            console.log('Received PushSubscription: ', JSON.stringify(pushSubscription));
            return pushSubscription;
        });

methods

  • ServiceWorkerRegistration.getNotifications()
    返回通过当前ServiceWorkerRegistration注册的一个通知列表。

  • ServiceWorkerRegistration.showNotification()
    显示push的请求标题。

// 添加service worker对push的监听
self.addEventListener('push', function (e) {
    var data = e.data;
    if (e.data) {
        data = data.json();
        console.log('push的数据为:', data);
        self.registration.showNotification(data.text);        
    } 
    else {
        console.log('push没有任何数据');
    }
});
  • ServiceWorkerRegistration.unregister()
    注销ServiceWorker并返回一个Promise。ServiceWorker将在注销之前完成所有正在进行的操作。
    如果想要取消缓存、不想要用SW了可以用unregister.
  • ServiceWorkerRegistration.update()
    在不查询缓存的情况下,检查ServiceWorker的更新版本。

install

InstallEvent
InstallEvent 接口表示一个 ServiceWorker 的 ServiceWorkerGlobalScope 上分派的安装操作。作为 ExtendableEvent 的一个子类,它确保在安装期间不调度诸如 FetchEvent 之类的功能事件。
一般来说我们在install这里缓存资源。具体代码放在下面。

值得一提的是instllEvent继承ExtendableEvent的一个方法waitUntil。上面已经介绍过了。

fetch

FetchEvent
这是会在 service worker 全局作用域中触发 fetch 事件的事件类型。它包含关于 fetch 的信息,包括 request 和接收方如何处理响应。它提供 event.respondWith() 方法,允许我们为此 fetch 提供一个响应。

self.addEventListener('fetch', function (fetchEvent) {
  console.log(fetchEvent)
  console.log('现在正在请求:' + fetchEvent.request.url);
});

在这里插入图片描述

我们监听fetch事件,返回的fetchEvent中是一个fetch请求的相关属性,介绍如下:

属性

  • clientId
    发起 fetch 的同源客户端的 id

  • request
    浏览器想要发送的 Request。
    如果我们想要看到这个请求的url,就可以使用request.url
    在这里插入图片描述

方法

  • FetchEvent.respondWith()
    阻止浏览器的默认 fetch 操作,并且由你自己提供一个响应(可以是一个 promise)。

  • ExtendableEvent.waitUntil()
    和上面的installEvent一样,继承了ExtendableEvent类的对象都会有这个方法。
    延长事件的生命周期。用于通知浏览器延长超出响应回复时间的任务,例如流和缓存。

activate

ServiceWorkerGlobalScope: activate event

MDN-删除缓存数据
PWA 应该在 service worker 的 activate (en-US) 事件中清除旧版本的任何缓存:当此事件触发时,service worker 可以确定没有之前版本的 service worker 正在运行,因此不再需要旧的缓存数据。

self.addEventListener("activate", (event) => {
  const cacheAllowlist = ["v2"];

  event.waitUntil(
    caches.forEach((cache, cacheName) => {
      if (!cacheAllowlist.includes(cacheName)) {
        return caches.delete(cacheName);
      }
    }),
  );
});

Web Workers API

MDN-渐进式 Web 应用(PWA)

Cache API

Cache

Cache 接口为缓存的 Request / Response 对象对提供存储机制,例如,作为ServiceWorker 生命周期的一部分。请注意,Cache 接口像 workers 一样,是暴露在 window 作用域下的。尽管它被定义在 service worker 的标准中,但是它不必一定要配合 service worker 使用。
 
一个域可以有多个命名 Cache 对象。你需要在你的脚本 (例如,在 ServiceWorker 中) 中处理缓存更新的方式。除非明确地更新缓存,否则缓存将不会被更新;除非删除,否则缓存数据不会过期。使用 CacheStorage.open(cacheName) 打开一个 Cache 对象,再使用 Cache 对象的方法去处理缓存。
你需要定期地清理缓存条目,因为每个浏览器都硬性限制了一个域下缓存数据的大小。缓存配额使用估算值,可以使用 StorageEstimate API 获得。浏览器尽其所能去管理磁盘空间,但它有可能删除一个域下的缓存数据。浏览器要么自动删除特定域的全部缓存,要么全部保留。确保按名称安装版本缓存,并仅从可以安全操作的脚本版本中使用缓存。

Cache.put, Cache.add和Cache.addAll只能在GET请求下使用。

Cache.add

Cache接口的 add() 方法接受一个 URL 作为参数,请求参数指定的 URL,并将返回的 response 对象添加到给定的 cache 中。

参数:
request 要添加到 cache 的 request。它可以是一个 Request 对象,也可以是 URL。
返回:
Promise

add() 方法在功能上等同于以下代码:

fetch(url).then(function (response) {
  if (!response.ok) {
    throw new TypeError("bad response status");
  }
  return cache.put(url, response);
});

使用示例:

下面的代码块等待 InstallEvent 事件触发,然后运行 waitUntil 来处理该应用程序的安装过程。包括调用 CacheStorage.open 来创建一个新的缓存,然后使用 Cache.add 来添加一个请求资源到该缓存。

this.addEventListener("install", function (event) {
  event.waitUntil(
    caches.open("v1").then(function (cache) {
      return cache.add("/sw-test/index.html");
    }),
  );
});

Cache.addAll

Cache 接口的 addAll() 方法接受一个 URL 数组,检索它们,并将生成的 response 对象添加到给定的缓存中。在检索期间创建的 request 对象成为存储的 response 操作的 key。

使用示例:

此代码块等待一个 InstallEvent 事件触发,然后运行 waitUntil 来处理该应用程序的安装进程。包括调用 CacheStorage.open 创建一个新的 cache,然后使用 addAll() 添加一系列资源。

this.addEventListener("install", function (event) {
  event.waitUntil(
    caches.open("v1").then(function (cache) {
      return cache.addAll([
        "/sw-test/",
        "/sw-test/index.html",
        "/sw-test/style.css",
        "/sw-test/app.js",
        "/sw-test/image-list.js",
        "/sw-test/star-wars-logo.jpg",
        "/sw-test/gallery/",
        "/sw-test/gallery/bountyHunters.jpg",
        "/sw-test/gallery/myLittleVader.jpg",
        "/sw-test/gallery/snowTroopers.jpg",
      ]);
    }),
  );
});

Cache.delete

Cache 接口的 delete() 方法查询 request 为 key 的 Cache 条目,如果找到,则删除该 Cache 条目并返回 resolve 为 true 的 Promise 。如果没有找到,则返回 resolve 为 false 的 Promise 。

cache.delete(request,{options}).then(function(true) {
  //your cache entry has been deleted
});

参数 options:

  • ignoreSearch: 一个 Boolean 值,指定匹配进程中是否忽略 url 中的查询字符串。如果设置为 true,http://foo.com/?value=bar 中的 ?value=bar 部分在执行匹配时会被忽略。默认为 false。
  • cacheName: A DOMString that represents a specific cache to search within. Note that this option is ignored by Cache.delete().

Cache.keys

Cache 接口的 keys() 方法返回一个 Promise ,这个 Promise 将解析为一个Cache 键的数组。
请求将以它们被插入的顺序返回。
参数options同上

cache.keys(request, { options }).then(function (keys) {
  //do something with your array of requests
});

Cache.match & Cache.matchAll

Cache 接口的 match() 方法,返回一个 Promise 解析为 (resolve to) 与 Cache 对象中的第一个匹配请求相关联的Response 。如果没有找到匹配,Promise 解析为 undefined。

matchAll匹配所有的请求。

参数:
request : 在Cache对象中查找的Request对象对应的 response。这个Request可以是 object 或者是一个 URL.
options:同上。

cache.match(request, { options }).then(function (response) {
  //操作 response
});

Cache.put

Cache.add/Cache.addAll 不会缓存 Response.status 值不在 200 范围内的响应,而 Cache.put 允许你存储任何请求/响应对。因此,Cache.add/Cache.addAll 不能用于不透明的响应,而 Cache.put 可以。
与add用法相同,更推荐add。

CacheStorage API

CacheStorage在代码中就是通过caches (复数)

  • delete()
  • has()
  • keys()
  • match()
  • open()

Clients API

Clients 提供对 Client 对象的访问。在 service worker 中使用 self.clients 使用。

Client

可以从 Clients.matchAll() 和 Clients.get() 等方法获取 Client/WindowClient 对象。

  • Client.postMessage()
    向客户端发送一条消息。
  • Client.id
    一个字符串,表示客户端的通用唯一标识。
  • Client.type
    表示客户端类型的字符串。可能是 “window”、“worker” 或 “sharedworker”。
  • Client.url
    表示客户端 URL 的字符串。

Clients方法

  • Clients.get()
    返回一个匹配给定 id 的 Client 的 Promise .

  • Clients.matchAll()
    返回一个 Client 对象数组的 Promise . options 参数允许你控制返回的 clients 类型。

  • Clients.openWindow()
    打开给定 URL 的新浏览器窗口,并返回新 WindowClient a 的 Promise .

  • Clients.claim()
    允许一个激活的 service worker 将自己设置为其scope 内所有 clients 的 controller .

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值