WebGL Tutorial
and more

应用缓存

撰写时间:2025-01-01

修订时间:2025-01-01

本章开始关注缓存脚本要完成的任务。主要涉及两大块的工作。一是在页面上完成注册的工作;二是在脚本完成安装及响应资源加载事件。

在网页端注册

上面的章节,我们详细考查了在注册过程中各种状态的转变。而在本章中,由于可以在脚本中响应对应的各类事件,因此我们反倒不必纠结繁琐的状态转换细节。同时,在注册问题上,应用前面所学知识,这里采用一种更为简便的方法:先检查、再注册。

下面是在页面端注册的代码:

async function doReg() { let reg = await navigator.serviceWorker.getRegistration('./'); if (reg) { pc.log('find previous reg.'); return; } else { pc.log('gonna reg...'); navigator.serviceWorker.register('caching.js', {scope: './'}) .then(reg => { pc.log('reg done.'); }); } } await doReg(); fetch('./demo.txt') .then(res => res.text()) .then(text => pc.log(text));

这些代码应放在网页的script中,在网页加载完毕后得以运行。而本站的PageConsole实用工具,可以在显示源代码的同时自动运行代码,加上Service Workers的注册是全局性的特点,因此产生了完全相同的效果。

如果之前在本路径下面已经注册过,则直接返回;否则予以注册。之后,加载本路径下面的demo.txt并打印其内容。

响应事件

Service Worker可响应2类事件。第一类为Service Worker对象创建时不同阶段的事件,包括installactivate事件。

第二类为基于动作的事件,包括fetch,以及pushmessage事件等等。

下面是caching脚本文件的内容:

self.addEventListener("install", event => { console.log(' Message from script: in install event ...'); event.waitUntil( caches.open("my-cache") .then(cache => { console.log(' Message from script: install finish.'); let resources = [ 'index.php', 'demo.txt' ]; return cache.addAll(resources); }) ); }); self.addEventListener("activate", event => { console.log(event.type); console.log(' Message from script: in activate event'); }); self.addEventListener("fetch", event => { console.log(' Message from script: in fetch event'); event.respondWith( caches.match(event.request).then(response => { return response || fetch(event.request); }).catch(() => { return caches.match("/fallback.html"); }) ); });

install事件在安装新的Service Worker时,或说,注册的installing所指向的对象改变时被触发,在此事件中使用caches对象来打开相应键名的配置,并将相关资源添加进缓存中。

activate事件在队列中轮候的Service Worker的状态转为激活时,或说,注册的active所指向的对象改变时被触发。

由于Service Workers不能访问DOM,因此只能将相应的信息通过console来输出。在桌面浏览器中打开开发者工具下的控制台,就会看到相应的信息。

Safari的Service Worker脚本中无法使用console。可使用Chrome浏览器来查看终端输出的结果。

install事件及activate事件响应函数中的参数event的类型为ExtendableEvent。其type属性值为诸如install, activate等。

ExtendableEventwaitUntil方法用以返回一个生命周期的Promise (lifetime promise) 。只有当此Promise得到解析后,后续的fetch事件才会被触发。

ExtendableEventtarget属性值为类型为ServiceWorkerGlobalScope的一个实例。

fetch事件响应函数中的参数event的类型为FetchEvent,它继承了ExtendableEvent。其respondWith方法用以决定如何根据请求来返回相应的页面。上面代码的意思为,如果在caches这个全局对象中找到相应的缓存页面,就返回这个缓存页面;否则,如实加载资源再返回;而如果此过程中出现错误,则返回在缴存中存有的fallback.html文件。

从上面代码可以看出,实际应用缓存的代码,实际上是非常简单的。

效果检验

在当前网面加载完毕后,Service Worker就已发生作用。现在,将WIFI断开,再刷新本页面,您仍可看到本页面的内容。但由于当前路径下只缓存了index.phpdemo.txt两个文件,没有其他的诸如CSS, JavaScrip等文件,因此,您会看到最原始的网页内容。

重新联网。现在,修改服务器端的caching.js文件的内容,例如随便增加一个空行,再重新刷新网页,在Chrome的终端中,您会看到以下信息输出:

Message from script: in install event ... Message from script: install finish.

这意味着,在有网络连接时,当客户端脚本内容与服务器端脚本内容不一致时,服务器端最新的Service Worker版本将会自动被安装。

这便是Service Workers的本质作用。

参考资源

Specifications

  1. Service Workers (W3C CR Draft)
  2. Events
  3. MessagePort