Service Worker概念和应用介绍
Posted 刘翾
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Service Worker概念和应用介绍相关的知识,希望对你有一定的参考价值。
Service workers
本质上充当Web应用程序与浏览器之间的代理服务器,也可以在网络可用时作为浏览器和网络间的代理. Service worker
是一个注册在指定源和路径下的事件驱动worker。它采用javascript
控制关联的页面或者网站,拦截并修改访问和资源请求,细粒度地缓存资源。你可以完全控制应用在特定情形(最常见的情形是网络不可用)下的表现。
Service worker
运行在worker
上下文,因此它不能访问DOM。相对于驱动应用的主JavaScript
线程,它运行在其他线程中,所以不会造成阻塞。它设计为完全异步,同步API(如XHR
和localStorage
)不能在service worker
中使用。
出于安全考量,Service workers
只能由HTTPS
承载,毕竟修改网络请求的能力暴露给中间人攻击会非常危险
使用 service worker 步骤
- 主进程通过
serviceWorker.register.(子进程service work文件路径)
来获取和注册
// js 执行主线程 main.js
navigator.serviceWorker.register('sw.js')
.then(function(registration)
console.log('Registered events at scope: ', registration.scope);
);
- 如果注册成功,
service worker
就在ServiceWorkerGlobalScope
环境中运行; 这是一个特殊类型的woker
上下文运行环境,与主运行线程(执行脚本)相独立,同时也没有访问DOM
的能力。 service worker
现在可以处理事件了。- 受
service worker
控制的页面第一次打开后会尝试去安装service worker
。最先发送给service worker
的事件是安装事件(在这个事件里可以开始进行填充IndexDB
和缓存站点资源)
// sw.js service worker子线程
// self为worker的全局
self.addEventListener('install', function(event)
event.waitUntil( // ExtendableEvent.waitUntil() 方法扩展了事件的生命周期。在服务工作线程中,延长事件的寿命从而阻止浏览器在事件中的异步操作完成之前终止服务工作线程。
caches.open('v1').then(function(cache) // caches也为service worker内部的全局变量
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/bountyHunters.jpg',
'/sw-test/gallery/myLittleVader.jpg',
'/sw-test/gallery/snowTroopers.jpg'
]);
)
);
);
- 当
install
事件的处理程序执行完毕后,ServiceWorker
进入installed
状态. 这时候主线程中返回的registration.waiting
属性代表进入installed
状态的ServiceWorker
navigator.serviceWorker.register('./sw.js').then(function(registration)
if (registration.waiting)
// Service Worker is Waiting
)
-
下一步是激活。当
service worker
安装完成后,如果在之前没有其他的service worker, 该sw会顺理进入下一阶段. 如果之前有service worker, 则该sw会等待一下三种情况.- 在新的
ServiceWorker
线程代码里,使用了self.skipWaiting()
- 或者当用户导航到别的网页,因此释放了旧的
ServiceWorker
时候 - 或者指定的时间过去后,释放了之前的
ServiceWorker
进入下一阶段的时候, 子线程(例子中的
sw.js
)会接收到一个激活事件(activate event)。activating
阶段主要用途是清理先前版本的service worker 脚本中使用的资源。 - 在新的
const cacheStorageKey = '该版本指定资源'
self.addEventListener('activate', function(e)
// 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]
)
)
)
当e.waitUntil
接收的Promise
进入成功状态后,ServiceWorker
的生命周期则进入activated
状态。这个时候主线程中的registration
的active
属性代表进入activated
状态的ServiceWorker
实例
navigator.serviceWorker.register('./sw.js').then(function(registration)
if (registration.active)
// Service Worker is Active
)
- Service Worker 现在可以控制页面了,这时候就可以做一些请求拦截的操作
self.addEventListener('fetch', function(event)
event.respondWith(
// caches.match()返回的总是resolves状态, 但如果匹配到之前的请求返回的会有值, 找不到返回undefined
caches.match(event.request).then(function()
return fetch(event.request).then(function(response)
return caches.open('v1').then(function(cache)
cache.put(event.request, response.clone()); // 放入缓存中
// clone 原因: 请求和响应流只能被读取一次。为了给浏览器返回响应以及把它缓存起来,我们不得不克隆一份。所以原始的会返回给浏览器,克隆的会发送到缓存中。它们都是读取了一次。
return response;
);
);
).catch(function()
return caches.match('/sw-test/gallery/myLittleVader.jpg');
)
);
);
参考链接:
https://developer.mozilla.org/zh-CN/docs/Web/API/Service_Worker_API/Using_Service_Workers
https://www.cnblogs.com/dojo-lzz/p/8047336.htm
以上是关于Service Worker概念和应用介绍的主要内容,如果未能解决你的问题,请参考以下文章
.NET Worker Service 添加 Serilog 日志记录