首页 > 其他分享 >Service Worker 实践与原理

Service Worker 实践与原理

时间:2023-04-29 20:44:40浏览次数:66  
标签:function 缓存 Service service Worker worker 实践 response fetch

Service Worker

在2014年,W3C公布了service worker的草案,service worker提供了很多新的能力,使得web app拥有与native app相同的离线体验、消息推送体验。 service worker是一段脚本,与web worker一样,也是在后台运行。作为一个独立的线程,运行环境与普通脚本不同,所以不能直接参与web交互行为。native app可以做到离线使用、消息推送、后台自动更新,service worker的出现是正是为了使得web app也可以具有类似的能力。

service worker 可以:

后台消息传递 网络代理,转发请求,伪造响应 离线缓存 消息推送 … … 本文以资源缓存为例,说明一下service worker是如何工作的。

上图是service worker生命周期,出处http://www.html5rocks.com/en/tutorials/service-worker/introduction/

图中可以看到,一个service worker要经历以下过程:

1. 安装

2. 激活

  • 激活成功之后,打开chrome://inspect/#service-workers可以查看到当前运行的service worker

3. 监听

  • 监听fetch和message事件,下面两种事件会进行简要描述

4. 销毁

  • 是否销毁由浏览器决定,如果一个service worker长期不使用或者机器内存有限,则可能会销毁这个worker;

fetch事件

在页面发起http请求时,service worker可以通过fetch事件拦截请求,并且给出自己的响应。 w3c提供了一个新的fetch api,用于取代XMLHttpRequest,与XMLHttpRequest最大不同有两点:

  1. fetch()方法返回的是Promise对象,通过then方法进行连续调用,减少嵌套。ES6的Promise在成为标准之后,会越来越方便开发人员。

  2. 提供了Request、Response对象,如果做过后端开发,对Request、Response应该比较熟悉。前端要发起请求可以通过url发起,也可以使用Request对象发起,而且Request可以复用。但是Response用在哪里呢?在service worker出现之前,前端确实不会自己给自己发消息,但是有了service worker,就可以在拦截请求之后根据需要发回自己的响应,对页面而言,这个普通的请求结果并没有区别,这是Response的一处应用。

下面是在http://www.sitepoint.com/introduction-to-the-fetch-api/中,作者利用fetch api通过fliker的公开api获取图片的例子,注释中详细解释了每一步的作用:

 1 /* 由于是get请求,直接把参数作为query string传递了 */
 2 var URL = 'https://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=your_api_key&format=json&nojsoncallback=1&tags=penguins';
 3 
 4 function fetchDemo() {
 5   // fetch(url, option)支持两个参数,option中可以设置header、body、method信息
 6   fetch(URL).then(function(response) {
 7     // 通过promise 对象获得相应内容,并且将响应内容按照json格式转成对象,json()方法调用之后返回的依然是promise对象
 8     // 也可以把内容转化成arraybuffer、blob对象
 9     return response.json();
10   }).then(function(json) {
11     // 渲染页面
12     insertPhotos(json);
13   });
14 }
15 
16 fetchDemo();

fetch api与XMLHttpRequest相比,更加简洁,并且提供的功能更全面,资源获取方式比ajax更优雅。兼容性方面:chrome 42开始支持,对于旧浏览器,可以通过官方维护的polyfill支持。

message事件

页面和serviceWorker之间可以通过posetMessage()方法发送消息,发送的消息可以通过message事件接收到。

这是一个双向的过程,页面可以发消息给service worker,service worker也可以发送消息给页面,由于这个特性,可以将service worker作为中间纽带,使得一个域名或者子域名下的多个页面可以自由通信。

利用 Service Worker 缓存文件

  • 首先注册sw.js 文件
1 if (navigator.serviceWorker) {
2     navigator.serviceWorker.register('service-worker.js').then(function(registration) {
3         console.log('service worker 注册成功');
4     }).catch(function (err) {
5         console.log('servcie worker 注册失败')
6     });
7 }

在上述代码中,注册了service-worker.js作为当前路径下的service worker。由于service worker的权限很高,所有的代码都需要是安全可靠的,所以只有https站点才可以使用service worker,当然localhost是一个特例。 注册完毕,现在开始写service-worker.js代码。

根据前面的生命周期图,在一个新的service worker被注册以后,首先会触发install事件,在service-workder.js中,可以通过监听install事件进行一些初始化工作,或者什么也不做。 因为我们是要缓存离线文件,所以可以在install事件中开始缓存,但是只是将文件加到caches缓存中,真正想让浏览器使用缓存文件需要在fetch事件中拦截。

  • 添加缓存
 1 var cacheFiles = [
 2     'about.js',
 3     'blog.js'
 4 ];
 5 self.addEventListener('install', function (evt) {
 6     evt.waitUntil(
 7         caches.open('my-test-cahce-v1').then(function (cache) {
 8             return cache.addAll(cacheFiles);
 9         })
10     );
11 });

这里首先定义了需要缓存的文件数组cacheFile,然后在install事件中,缓存这些文件。 evt是一个InstallEvent对象,继承自ExtendableEvent,其中的waitUntil()方法接收一个promise对象,直到这个promise对象成功resolve之后,才会继续运行service-worker.js。 caches是一个CacheStorage对象,使用open()方法打开一个缓存,缓存通过名称进行区分。 获得cache实例之后,调用addAll()方法缓存文件。

  • 浏览器使用缓存 拦截fetch事件
 1 // 缓存图片
 2 self.addEventListener('fetch', function (evt) {
 3     evt.respondWith(
 4         caches.match(evt.request).then(function(response) {
 5             if (response) {
 6                 return response;
 7             }
 8             var request = evt.request.clone();
 9             return fetch(request).then(function (response) {
10                 if (!response && response.status !== 200 && !response.headers.get('Content-type').match(/image/)) {
11                     return response;
12                 }
13                 var responseClone = response.clone();
14                 caches.open('my-test-cache-v1').then(function (cache) {
15                     cache.put(evt.request, responseClone);
16                 });
17                 return response;
18             });
19         })
20     )
21 });

通过监听fetch事件,service worker可以返回自己的响应。

首先检缓存中是否已经缓存了这个请求,如果有,就直接返回响应,就减少了一次网络请求。否则由service workder发起请求,这时的service workder起到了一个中间代理的作用。

service worker请求的过程通过fetch api完成,得到response对象以后进行过滤,查看是否是图片文件,如果不是,就直接返回请求,不会缓存。

如果是图片,要先复制一份response,原因是request或者response对象属于stream,只能使用一次,之后一份存入缓存,另一份发送给页面。 这就是service worker的强大之处:拦截请求,伪造响应。fetch api在这里也起到了很大的作用。

service worker的更新很简单,只要service-worker.js的文件内容有更新,就会使用新的脚本。但是有一点要注意:旧缓存文件的清除、新文件的缓存要在activate事件中进行,因为可能旧的页面还在使用之前的缓存文件,清除之后会失去作用。

Service worker 出现的问题

1 运行时间

  • service worker并不是一直在后台运行的。在页面关闭后,浏览器可以继续保持service worker运行,也可以关闭service worker,这取决与浏览器自己的行为。 所以尽量避免在service worker 中使用全局变量。可能会造成结果不准确。

2 权限太大

  • 当service worker监听fetch事件以后,对应的请求都会经过service worker。通过chrome的network工具,可以看到此类请求会标注:from service worker。如果service worker中出现了问题,会导致所有请求失败,包括普通的html文件。所以service worker的代码质量、容错性一定要很好才能保证web app正常运行。

 

标签:function,缓存,Service,service,Worker,worker,实践,response,fetch
From: https://www.cnblogs.com/taue997/p/17364453.html

相关文章

  • 云LIS系统基于ASP.NET CORE 3.1 MVC + SQLserver + Redis技术实践
    云LIS   利用云LIS实现区域内各级医院门诊、住院等日常医疗业务和行政业务的全流程管理和医院的无纸化运营,规范就医流程,提升医疗质量,提供科学决策支持,增强患者的就医体验。云LIS是为区域医疗提供临床实验室信息服务的计算机应用程序,可协助区域内所有临床实验室相互协调并......
  • 西门子成都工厂的DevSecOps实践
    大家好,我是Edison。4月15日,成都.NET线下技术沙龙活动中,我分享了一个主题《西门子成都工厂的DevSecOps实践》,向大家介绍了我们为什么要做DevSecOps以及我们目前是怎么做DevSecOps的。整个分享从Why-What-How的顺序讲解,基于我们目前正在使用的.NET6技术栈,我们也给出了一些参考......
  • VS2010创建Webservice程序
    VisualStudio2010中已经找不到直接创建WebService的模板方式了,但下面的方法可心实现:  在VisualStudio2010的新建Web应用程序或者Web网站窗口中,如果你选择.NET4.0,会发现缺少了ASP.NETWebServices模板。你可能会怀疑VS2010是不是不支持ASP.NETWebServices......
  • Java 项目中一种简单的动态修改配置即时生效的方式 WatchService
    这种方式仅适合于比较小的项目,例如只有一两台服务器,而且配置文件是可以直接修改的。例如Springmvc以war包的形式部署,可以直接修改resources中的配置文件。如果是Springboot项目,还想用这种方式的话,就要引用一个外部可以编辑的文件,比如一个固定的目录,因为springboot大多......
  • 服务百万商家的系统,发布风险如何规避?微盟全链路灰度实践
    一分钟精华速览全链路灰度发布是指在微服务体系架构中,应用的新、旧版本间平滑过渡的一种发布方式。由于微服务之间依赖关系错综复杂,一次发布可能会涉及多个服务升级,所以在发布前进行小规模的生产环境验证,让新版本的应用实例来承接、处理限定规模或范围的业务流量,能最大限度控制发......
  • 长尾关键词挤掉竞争对手?这些最佳实践分享可助你一臂之力!
    现在,你已经掌握了SEO的流程,知晓了网站优化的各种方法,也清楚了站外优化的技巧,但问题又来了:你知道优化网站,竞争对手也知道;你懂得站外优化,竞争对手也懂。在这种情况下,你又该如何让你的网站在海量搜索结果中脱颖而出呢?别慌,有一招可以做到,我们称之为:长尾词策略。所谓“长尾关键词(简称:长......
  • Memcache实践总结【转】
    附件为ppt介绍memcached基本问题1、memcached的基本设置 1)启动Memcache的服务器端 #/usr/local/bin/memcached-d-m10-uroot-l192.168.0.200-p12000-c256-P/tmp/memcached.pid-d选项是启动一个守护进程, -m是分配给Memcache使用的内存数量,单位是MB,我这里是10MB, -u......
  • [ML&DL] 深度学习的实践层面
    深度学习的实践层面训练集验证集测试集过程神经网络的训练是一个需要不断迭代的过程,一般先提出idea,然后编码实现、测试,根据测试结果再次调整思路......分组与比例数据集通常分为3个部分:训练集、验证集和测试集。训练集用于训练模型的参数。验证集用于选择最好的模型。......
  • 5月7日【飞天Club × 云原生技术实践营—飞天免费计划实践专场】开启报名
    点击此处或扫描文末二维码免费报名参加活动福利:1、云谷游园,开发者面对面2、云原生产品免费试用,ApsaraClouder函数计算免费考证3、完成动手体验并通过考证即可现场获得精美礼品一份!4、现场多轮抽奖,精美好礼送不停!时间: 2023.5.7(周日)14:00-17:00地点:阿里巴巴云谷园区2号楼......
  • 网安等保-国产Linux操作系统银河麒麟KylinOS-V10SP3常规配置、系统优化与安全加固基线
    [点击......