Skip to Content

面试导航 - 程序员面试题库大全 | 前端后端面试真题 | 面试

Javascript前端断网之后正常显示其他内容

在现代的网络世界里,5G 网络的普及,我们可以访问一个网站或者使用一个 App 的速度极其快,但是在没有网络的情况下你啥都看不了,只能大眼瞪小眼了。

离线应用是指通过离线缓存技术,让资源在第一次被加载后缓存在本地,下次访问它时就直接返回本地的文件,就算没有网络连接。

通过离线应用,主要有以下几个优点:

  1. 在没有网络的情况下也能打开网页。
  2. 由于部分被缓存的资源直接从本地加载,对用户来说可以加速网页加载速度,对网站运营者来说可以减少服务器压力以及传输流量费用。

离线应用的核心是离线缓存技术,要实现这种方式,我们可以使用 Service Worker 来实现这种缓存技术。

什么是 Service Worker

Service Worker 服务器和浏览器之间的桥梁或者中间人。

Service Worker 运行在一个与页面 JavaScript 主线程独立的线程上,并且无权访问 DOM 结构。但是它能拦截当前网站所有的请求,对请求使用相应的逻辑进行判断,如果需要向服务器发起请求的就转给服务器,如果可以直接使用缓存的就直接返回缓存不再转给服务器。从而大大提高浏览体验。

注册 Service Worker

要使用 Service Worker,首先我们要判断浏览器是否支持 Service Worker,具体代码逻辑如下:

if (navigator.serviceWorker) { window.addEventListener('DOMContentLoaded', function () { navigator.serviceWorker.register('/worker.js'); }); }

这段代码的主要目的是在支持 Service Worker 的浏览器中,当页面加载完成后注册一个指定的 Service Worker 脚本。这个传入的 worker.js 就是 Service Worker 的运行环境。

这个脚本被安装到浏览器中后,就算用户关闭了当前网页,它仍会存在。 也就是说第一次打开该网页时 Service Workers 的逻辑不会生效,因为脚本还没有被加载和注册,但是以后再次打开该网页时脚本里的逻辑将会生效。

Service Worker 安装和激活

注册完成后,worker.js 文件会自动下载、安装,然后激活。它提供了一些 API 给我们做一些监听事件:

self.addEventListener('install', function (e) { console.log('Service Worker 安装成功'); }); self.addEventListener('fetch', function (event) { console.log('service worker is fetch'); });

当 install 完成并且成功激活之后,就能够监听 fetch 操作了,如上代码所示,输出结构如下图所示:

使用 Service Workers 实现离线缓存

在上面的内容我们已经知道了 Service Workers 在注册成功后会在其生命周期中派发出一些事件,通过监听对应的事件在特点的时间节点上做一些事情。

在 Service Workers 安装成功后会派发出 install 事件,需要在这个事件中执行缓存资源的逻辑,实现代码如下:

// 当前缓存版本的唯一标识符,用当前时间代替 const cacheKey = new Date().toISOString(); // 需要被缓存的文件的 URL 列表 const cacheFileList = ['/index.html', '/index.js', '/index.css']; // 监听 install 事件 self.addEventListener('install', function (event) { // 等待所有资源缓存完成时,才可以进行下一步 event.waitUntil( caches.open(cacheKey).then(function (cache) { // 要缓存的文件 URL 列表 return cache.addAll(cacheFileList); }), ); });

在 install 阶段我们就已经指定了要被缓存的内容了,那么就可以在 fetch 阶段中听网络请求事件去拦截请求,复用缓存,代码如下:

self.addEventListener('fetch', function (event) { event.respondWith( // 去缓存中查询对应的请求 caches.match(event.request).then(function (response) { // 如果命中本地缓存,就直接返回本地的资源 if (response) { return response; } // 否则就去用 fetch 下载资源 return fetch(event.request); }), ); });

通过上面的操作,创建和添加了一个缓存的库,如下图所示:

缓存更新

线上的代码有时需要更新和重新发布,如果这个文件被离线缓存了,那就需要 Service Workers 脚本中有对应的逻辑去更新缓存。

这可以通过更新 Service Workers 脚本文件做到,浏览器针对 Service Worker 有如下机制:

  1. 每次打开接入了 Service Workers 的网页时,浏览器都会去重新下载 Service Workers 脚本文件,如果发现和当前已经注册过的文件存在字节差异,就将其视为新服务工作线程。
  2. 新 Service Workers 线程将会启动,且将会触发其 install 事件。
  3. 当网站上当前打开的页面关闭时,旧 Service Workers 线程将会被终止,新 Service Workers 线程将会取得控制权。
  4. 新 Service Workers 线程取得控制权后,将会触发其 activate 事件。

新 Service Workers 线程中的 activate 事件就是最佳的清理旧缓存的时间点,代码如下:

var cacheWhitelist = [cacheKey]; self.addEventListener('activate', function (event) { event.waitUntil( caches.keys().then(function (cacheNames) { return Promise.all( cacheNames.map(function (cacheName) { // 不在白名单的缓存全部清理掉 if (cacheWhitelist.indexOf(cacheName) === -1) { // 删除缓存 return caches.delete(cacheName); } }), ); }), ); });

这样能确保只有那些我们需要的文件会保留在缓存中,我们不需要留下任何的垃圾,毕竟浏览器的缓存空间是有限的,手动清理掉这些不需要的缓存是不错的主意。

参考资料

总结

Service Worker 作为服务器和浏览器两者之间的桥梁,它并且可以缓存技术,通过这种方式,在断网的时候,去获取缓存中相应的数据以展示给客户显示。

当断网之后,直接给他页面返回一个俄罗斯方块让他玩足一整天。

最后更新于:
Copyright © 2025Moment版权所有粤ICP备2025376666