【澳门萄京赌场网站】Service Worker初体验

Service Worker初体验

2016/01/06 · JavaScript
· Service Worker

原稿出处: AlloyTeam   

在贰零壹肆年,W3C宣布了service worker的草案,service
worker提供了重重新的力量,使得web app拥有与native
app相同的离线体验、音信推送体验。
service worker是一段脚本,与web
worker一样,也是在后台运营。作为2个单独的线程,运行环境与经常脚本不相同,所以无法直接到场web交互行为。native
app可以已毕离线使用、音讯推送、后台自动更新,service
worker的产出是多亏为了使得web app也足以拥有类似的能力。

 

service worker可以:

  1. 后台音信传递
  2. 互连网代理,转载呼吁,伪造响应
  3. 离线缓存
  4. 音信推送
  5.  … …

正文以能源缓存为例,说喜宝下service worker是怎么样工作的。

Service Worker是什么


从效果上的话,Service Worker是一种提供离线缓存控制成效的一种Worker,同时,也有所消息推送和后台同步的意义,可以经过ServiceWorker来缓存网页的能源,然后拦截Fetch请求来举办相应的缓存处理操作。因为是一种Worker,所以ServiceWorker也存有Worker的部分宗旨特征,例如:

  • 独立于主线程运营
  • 不可以访问window对象,可是拥有本人的1个推行上下文,例如Service WorkerServiceWorkerGlobalScope
  • 有着消息api来和页面举行新闻交互

瑟维斯Worker是一种共享型Worker,它差距于专用型Worker只可以在成立它的页面中行使,默认配置下,service
Worker可以被目前登记脚本的域名下有所页面公用。
相当于说,只要在二个根域名注册一个ServiceWorker,那么具有那几个域名下的页面都会吸收影响。

作用:

可以使您的采取先走访当地缓存财富,所以在离线状态时,在未曾通过网络收到到愈多的数量前,还是可以提供基本的作用。

简书放不了demo,demo可以看原文

生命周期

先来看一下二个service worker的周转周期

澳门萄京赌场网站 1
上图是service
worker生命周期,出处

【澳门萄京赌场网站】Service Worker初体验。图中得以看到,二个service worker要经历以下进程:

  1.  安装

2.
 激活,激活成功未来,打开chrome://inspect/#service-workers能够查阅到近来运作的service
worker

澳门萄京赌场网站 2

  1. 监听fetch和message事件,上边三种事件会展开简要描述

  2. 销毁,是还是不是销毁由浏览器决定,借使多少个service
    worker长期不选用依然机器内存有数,则只怕会销毁那些worker

Service Worker使用


要采纳ServiceWorker,首先,要求经过serviceWorkerContainer.register()来拓展注册,例如:

ServiceWorkerContainer.register("/test/service.js", {scope:"./"})
    .then(
        function(ServiceWorkerRegistration) {
            // do something
        }
);

只要当前域名为www.baidu.com/serviceWork,那么地点的章程就在www.baidu.com/serviceWork/test上边注册了一个ServiceWorker,如果把scope改成./hahaha,那么功能域就改为了www.baidu.com/serviceWork/test/hahaha,只要处于这么些域名之下的具有页面,都饱受那个ServiceWorker的决定。可是,假使将scope改成”../”,页面就会报出一个张冠李戴,因为此时不允许设置比service.js所在地点层级更高的门径,除非添加2个Service-Worker-Allowedheader。

挂号成功之后,受控界面会去安装serviceWorker,安装已毕现在会处在等候状态,接下去有只怕会进去激活状态,激活状态之后,页面还不肯定是受控的,不过有相应的api可以决定这一种种流程。那个流程就是ServiceWorker最最复杂的生命周期了。

接纳前的设置:

Chrome中必要打开相关配置: 访问
chrome://flags 并开启
experimental-web-platform-features; 重启浏览器
(注意:某本天性在Chrome中绝非暗许开放支持);其它,你需求通过 HTTPS
来访问你的页面 — 出于安全原因,Service Workers 须要要在必须在 HTTPS
下才能运维,localhost 也被浏览器认为是安全源。

Service Worker 是什么?

service worker 是独立于近来页面的一段运维在浏览器后台进度里的本子。
service worker不必要用户打开 web
页面,也不需求其它交互,异步地运营在七个通通独立的上下文环境,不会对主线程造成堵塞。基于service
worker可以完毕音讯推送,静默更新以及地理围栏等服务。
service
worker提供一种渐进增强的性状,使用个性检测来逐步增强,不会在老旧的不帮忙service workers 的浏览器中发出震慑。可以透过service
workers化解让应用程序可以离线工作,让存储数据在离线时行使的标题。

注意事项:
1.service
worker运营在它们本身的完全独创新步的大局上下文中,约等于说它们有友好的容器。
2.service
worker并未间接操作DOM的权柄,可是足以经过postMessage方法来与Web页面通信,让页面操作DOM。
3.service
worker是3个可编程的网络代理,允许开发者控制页面上处理的互联网请求。
4.浏览器只怕每一日回收service
worker,在不被拔取的时候,它会融洽终止,而当它再度被用到的时候,会被重复激活。
5.service worker的生命周期是由事件驱动的而不是经过Client。

fetch事件

在页面发起http请求时,service
worker可以通过fetch事件拦截请求,并且付诸本人的响应。
w3c提供了2个新的fetch
api,用于代替XMLHttpRequest,与XMLHttpRequest最大差距有两点:

1.
fetch()方法再次来到的是Promise对象,通过then方法开展两次三番调用,收缩嵌套。ES6的Promise在成为专业将来,会愈来愈便利开发人员。

2. 提供了Request、Response对象,固然做过后端开发,对Request、Response应该相比精通。前端要倡导呼吁可以透过url发起,也足以接纳Request对象发起,而且Request可以复用。不过Response用在何地吗?在service
worker出现以前,前端确实不会融洽给协调发音讯,可是有了service
worker,就可以在拦截请求之后据悉需求发回本身的响应,对页面而言,那几个一般的乞请结果并不曾分别,那是Response的一处采取。

上边是在中,我运用fetch
api通过fliker的当众api获取图片的例证,注释中详细解释了每一步的效劳:

JavaScript

/* 由于是get请求,直接把参数作为query string传递了 */ var URL =
”;
function fetchDemo() { // fetch(url,
option)扶助七个参数,option中能够安装header、body、method新闻fetch(U昂科雷L).then(function(response) { // 通过promise
对象拿到相应内容,并且将响应内容依照json格式转成对象,json()方法调用之后回来的依旧是promise对象
// 也足以把内容转化成arraybuffer、blob对象 return response.json();
}).then(function(json) { // 渲染页面 insertPhotos(json); }); }
fetchDemo();

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

fetch
api与XMLHttpRequest相比较,特别简洁,并且提供的法力更完善,财富获取格局比ajax更优雅。包容性方面:chrome
42始发辅助,对于旧浏览器,可以经过法定维护的polyfill协理。

ServiceWorker生命周期


serviceWorker的生命周期有点复杂,情形多多,可是大多符合3个理念,这就是渐进式。

简易的事例

那是把express和sw-test容易结合的多少个小demo, 项目周转起来访问
http://localhost:3000/sw-test/index.html
,
然后停下此服务仍是可以访问相应能源。Github

Service Worker生命周期

service worker拥有三个全然独立于Web页面的生命周期

澳门萄京赌场网站 3

sw-lifecycle.png

  1. 注册service worker,在网页上生效
  2. 安装成功,激活 只怕 安装战败(下次加载会尝试重新安装)
  3. 激活后,在sw的效果域下效率具有的页面,首次决定sw不会生效,下次加载页面才会生效。
  4. sw作用页面后,处理fetch(互联网请求)和message(页面音讯)事件 或然被终止(节外省存)。

message事件

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

那是1个双向的历程,页面可以发音信给service worker,service
worker也得以发送音信给页面,由于那个本性,可以将service
worker作为中间纽带,使得1个域名还是子域名下的三个页面可以随便通讯。

此处是2个小的页面之间通讯demo

install

实施完登记之后,浏览器会去下载,假诺脚本没有不当的话,就会开展安装,安装会在Worker内触发install事件,安装分为多少个景况:installinginstalled,那里可以推行一些操作。

self.addEventListener("install",installEvent=>{
    self.skipWaiting();//跳过waiting
    installEvent.waitUntil(
        caches.open(CACHE_NAME).then(cache=>{
            return cache.add("http://upload.jianshu.io/users/upload_avatars/9545112/f186bd4a-1da4-4912-b926-a744bc128d06.png?imageMogr2/auto-orient/strip|imageView2/1/w/240/h/240");
        })
    )

});

此处会有1个install伊夫nt,通过waitUtil格局可以卡住安装状态,这个点子可以流传2个promise,唯有这么些promise正确resolve之后,才会已毕安装,同时,还有3个skipwaiting方法,那一个艺术可以跳过installed和activating状态之间的waiting状态。
首次打开页面会安装work,然后接下去再检测到新的work也会再度实施安装。
接触更新的二种情景:

  • 先是次导航到功用域范围内页面的时候
  • 当在24小时内并未开展更新检测并且触发作用性时间如push或sync的时候
  • SW 的 UOdysseyL 爆发变化并调用.register()时
  • 手动执行reg.update()
  • 重载页面(某些意况下不会更新,原因不明)

创新会比对旧版本和新本子的字节,假诺字节不平等,则更新。在立异install完结之后,会跻身waiting状态,直到旧版本不控制任何client(受控的页面)再进入activating状态。

连锁代码

  • /public/sw-test/app.js
  1. 首先判断了浏览器是或不是帮忙
  2. 调用 register 方法注册 service worker, 第三个参数是运作 service
    worker 的
    js 文件, 第3个 scope 参数是选填的,能够被用来指定你想让 service
    worker 控制的故事情节的子目录。 在那么些事例,我们指定了 ‘/sw-test/’,即
    http://localhost:3000/sw-test/
    下的伏乞会被抓走, 被指定的能源会被缓存。
  3. register 方法重回2个 Promise , 实行不易错误处理。

  if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('/sw-test/sw.js', { scope: '/sw-test/' }).then(function(reg) {
    // registration worked
    console.log('Registration succeeded. Scope is ' + reg.scope);
  }).catch(function(error) {
    // registration failed
    console.log('Registration failed with ' + error);
  });
}
  • /public/sw-test/sw.js
    大旨文件,监听安装事件, 打开缓存 v1 增添内需缓存财富 request url
    list, 截取被控文件下请求, 即使不存在该缓存则开展缓存处理
  1. 监听了 install 事件, event.waitUntil 首要用在 Install, activate
    事件中,
    在劳动办事线程中,延长事件的寿命从而阻碍浏览器在事件中的异步操作完毕之前终止服务办事线程。
  2. Cache 接口提供缓存的
    Request,
    Response
    对象对的囤积机制,例如作为ServiceWorker生命周期的一部分。
    Cache 接口像 workers 一样, 是暴光在 window
    成效域下的。即便它被定义在 service worker 的专业中,
    然则它不用一定要合营 service worker
    使用.Cache详细API
  3. event.respondWith
    方法目的在于包裹代码,那一个代码为来源受控页面的request生成自定义的response,翻看更加多。response.clone()
    创设了一个响应对象的仿造,这一个目的在全部地点都是平等的,可是存储在1个例外的变量中。防止频仍采取篡改了目的。

self.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/bountyHunters.jpg',
        '/sw-test/gallery/myLittleVader.jpg',
        '/sw-test/gallery/snowTroopers.jpg'
      ]);
    })
  );
});

self.addEventListener('fetch', function(event) {
  event.respondWith(caches.match(event.request).then(function(response) {
    // caches.match() always resolves
    // but in case of success response will have value
    if (response !== undefined) {
      return response;
    } else {
      return fetch(event.request).then(function (response) {
        // response may be used only once
        // we need to save clone to put one copy in cache
        // and serve second one
        let responseClone = response.clone();

        caches.open('v1').then(function (cache) {
          cache.put(event.request, responseClone);
        });
        return response;
      }).catch(function () {
        return caches.match('/sw-test/gallery/myLittleVader.jpg');
      });
    }
  }));
});

Service Worker支持接纳

使用service workder缓存文件

上边介绍三个用到service worker缓存离线文件的事例
预备index.js,用于注册service-worker

JavaScript

if (navigator.serviceWorker) {
navigator.serviceWorker.register(‘service-worker.js’).then(function(registration)
{ console.log(‘service worker 注册成功’); }).catch(function (err) {
console.log(‘servcie worker 注册失利’) }); }

1
2
3
4
5
6
7
if (navigator.serviceWorker) {
    navigator.serviceWorker.register(‘service-worker.js’).then(function(registration) {
        console.log(‘service worker 注册成功’);
    }).catch(function (err) {
        console.log(‘servcie worker 注册失败’)
    });
}

在上述代码中,注册了service-worker.js作为当前路线下的service
worker。由于service
worker的权位很高,全部的代码都需假使安全可信赖的,所以唯有https站点才得以应用service
worker,当然localhost是多少个特例。
挂号甘休,未来开班写service-worker.js代码。
据悉前面的生命周期图,在3个新的service
worker被登记之后,首先会触发install事件,在service-workder.js中,可以经过监听install事件开展一些开始化工作,或然怎么着也不做。
因为大家是要缓存离线文件,所以可以在install事件中初露缓存,不过只是将文件加到caches缓存中,真正想让浏览器拔取缓存文件必要在fetch事件中截留

JavaScript

var cacheFiles = [ ‘about.js’, ‘blog.js’ ];
self.addEventListener(‘install’, function (evt) { evt.waitUntil(
caches.open(‘my-test-cahce-v1’).then(function (cache) { return
cache.addAll(cacheFiles); }) ); });

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

首先定义了亟待缓存的文书数组cacheFile,然后在install事件中,缓存这几个文件。
evt是3个Install伊夫nt对象,继承自Extendable伊芙nt,其中的waitUntil()方法接收二个promise对象,直到这些promise对象成功resolve之后,才会继续运营service-worker.js。
caches是一个CacheStorage对象,使用open()方法打开一个缓存,缓存通过名称进行区分。
获取cache实例之后,调用addAll()方法缓存文件。

诸如此类就将文件添加到caches缓存中了,想让浏览器采用缓存,还须求拦截fetch事件

JavaScript

// 缓存图片 self.add伊夫ntListener(‘fetch’, function (evt) {
evt.respondWith( caches.match(evt.request).then(function(response) { if
(response) { return response; } var request = evt.request.clone();
return fetch(request).then(function (response) { if (!response &&
response.status !== 200 &&
!response.headers.get(‘Content-type’).match(/image/)) { return response;
} var responseClone = response.clone();
caches.open(‘my-test-cache-v1’).then(function (cache) {
cache.put(evt.request, responseClone); }); return response; }); }) ) });

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

通过监听fetch事件,service worker可以回来自个儿的响应。

先是检缓存中是还是不是早已缓存了这一个请求,尽管有,就径直回到响应,就减弱了两遍网络请求。否则由service
workder发起请求,那时的service workder起到了1个中间代理的效用。

service worker请求的进度通过fetch
api完毕,得到response对象将来举行过滤,查看是不是是图片文件,若是或不是,就一向回到请求,不会缓存。

假定是图形,要先复制一份response,原因是request可能response对象属于stream,只好动用一回,之后一份存入缓存,另一份发送给页面。
那就是service worker的兵不血刃之处:拦截请求,伪造响应。fetch
api在此地也起到了很大的效能。

 

service
worker的翻新很粗略,只要service-worker.js的文本内容有创新,就会拔取新的剧本。可是有有个别要专注:旧缓存文件的解除、新文件的缓存要在activate事件中展开,因为大概旧的页面还在应用此前的缓存文件,清除之后会错过意义。

 

在初次使用service worker的进度中,也蒙受了有个别标题,上边是里面七个

activate

activate的事态比测试妹子的盘算逻辑还难揣摸。可是那么些依据三个规格,唯有全部的页面都不受老的serviceWorker控制的时候,才会早先激活。意思就是独具worker功效的页面都关了,相当于重启更新,再次运维的时候,才会跻身激活状态。激活也会触发3个activate状态.

self.addEventListener("activate", ExtendableEvent => {
  ExtendableEvent.waitUntil(self.clients.claim());
 }

activate也和install一样,也有waitUtil方法,效果也是平等的。激活成功未来实际还不肯定有效益,因为页面只怕还处在不受控的事态,或许有此外3个页面,没有刷新的,不过这一个时候新开二个页面更新了work,那几个时候就须要调用clients.claim操作来让具备打开的页面受控。但是…work的执行是异步的,也等于说,页面在举办这么些艺术在此之前是不受控,或许是还是不是受最新的work控制的,在使用work来缓存的时候,就会冒出难点,导致版本差别,所以,个人感觉serviceWorker相比较符合做一个资助者,没有也行,有也行,可以经过安装2个button之类的来提醒用户,发现新本子,是不是需求刷新之类的操作。
下边这张图很好的包括了生命周期

澳门萄京赌场网站 4

生命周期

本子更新删除旧缓存

  1. 监听 activate 事件, 如当前版本 v2,删除与最近不匹配缓存数据。

this.addEventListener('activate', function(event) {
  var cacheWhitelist = ['v2'];

  event.waitUntil(
    caches.keys().then(function(keyList) {
      return Promise.all(keyList.map(function(key) {
        if (cacheWhitelist.indexOf(key) === -1) {
          return caches.delete(key);
        }
      }));
    })
  );
});

浏览器资助

service worker
support

澳门萄京赌场网站 5

navigator-serviceworker.png

相关文章