菜单

Service Worker初体验

2019年4月9日 - Bootstrap

采用service workder缓存文件

上面介绍1个采纳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代码。
依照后边的生命周期图,在1个新的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是八个Install伊夫nt对象,继承自Extendable伊芙nt,其中的waitUntil()方法接收二个promise对象,直到这一个promise对象成功resolve之后,才会持续运维service-worker.js。
caches是3个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能够回来本身的响应。

率先检缓存中是还是不是业已缓存了那一个请求,要是有,就直接回到响应,就减少了3回网络请求。不然由service
workder发起请求,那时的service workder起到了一个当中代理的功用。

service worker请求的进度通过fetch
api完毕,获得response对象未来举行过滤,查看是或不是是图片文件,假诺不是,就平昔回到请求,不会缓存。

借使是图片,要先复制1份response,原因是request恐怕response对象属于stream,只好选取叁回,之后1份存入缓存,另一份发送给页面。
那正是service worker的强劲之处:拦截请求,伪造响应。fetch
api在那里也起到了十分大的效果。

 

service
worker的翻新不会细小略,只要service-worker.js的文本内容有更新,就会选拔新的本子。可是有好几要小心:旧缓存文件的铲除、新文件的缓存要在activate事件中举办,因为大概旧的页面还在利用在此之前的缓存文件,清除之后会错过成效。

 

在第一使用service worker的进程中,也遇到了某个标题,上边是中间多少个

简言之的例子

那是把express和sw-test简单结合的1个小demo, 项目运行起来访问
http://localhost:3000/sw-test/index.html
,
然后截止此服务还能访问相应能源。Github

难点一. 运转时刻

service
worker并不是直接在后台运行的。在页面关闭后,浏览器能够一连保持service
worker运维,也能够关闭service
worker,这有赖于与浏览器本人的作为。所以不要定义一些全局变量,例如上面的代码(来自https://jakearchibald.com/2014/service-worker-first-draft/):

JavaScript

var hitCounter = 0; this.addEventListener(‘fetch’, function(event) {
hitCounter++; event.respondWith( new Response(‘Hit number ‘ +
hitCounter) ); });

1
2
3
4
5
6
7
8
var hitCounter = 0;
 
this.addEventListener(‘fetch’, function(event) {
  hitCounter++;
  event.respondWith(
    new Response(‘Hit number ‘ + hitCounter)
  );
});

回去的结果恐怕是从未有过规律的:1,二,一,二,一,壹,二….,原因是hitCounter并从未平昔留存,即使浏览器关闭了它,下次早先的时候hitCounter就赋值为0了
那般的事情导致调节和测试代码困难,当你更新三个service
worker现在,唯有在开辟新页面以往才也许应用新的service
worker,在调节进度中时常等上一两分钟才会利用新的,相比较抓狂。

参照 MDN

Service Worker
详细文书档案

message事件

页面和serviceWorker之间能够透过posetMessage()方法发送新闻,发送的音信能够由此message事件接收到。

那是二个双向的经过,页面可以发消息给service worker,service
worker也足以发送音讯给页面,由于那个特点,可以将service
worker作为中间纽带,使得一个域名依旧子域名下的多个页面能够自由通讯。

那里是五个小的页面之间通讯demohttps://nzv3tos3n.qnssl.com/message/msg-demo.html

有关代码

  1. 先是判断了浏览器是不是扶助
  2. 调用 register 方法注册 service worker, 第二个参数是运作 service
    worker 的
    js 文件, 第二个 scope 参数是选填的,能够被用来钦点你想让 service
    worker 控制的剧情的子目录。 在这么些例子,大家钦命了 ‘/sw-test/’,即
    http://localhost:3000/sw-test/
    下的乞请会被抓走, 被钦命的能源会被缓存。
  3. register 方法重返3个 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);
  });
}
  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初体验

2016/01/06 · JavaScript
· Service Worker

初稿出处: AlloyTeam   

在201四年,W3C发布了service worker的草案,service
worker提供了无数新的能力,使得web app拥有与native
app相同的离线体验、新闻推送体验。
service worker是1段脚本,与web
worker一样,也是在后台运维。作为三个单独的线程,运转条件与平常脚本区别,所以不可能直接出席web交互行为。native
app可以成功离线使用、消息推送、后台自动更新,service
worker的产出是多亏为了使得web app也足以拥有类似的能力。

 

service worker可以:

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

正文以能源缓存为例,说美素佳儿(Friso)下service worker是怎么样工作的。

本子更新删除旧缓存

  1. 监听 activate 事件, 如当前版本 v贰,删除与方今不相称缓存数据。

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的运作周期

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

图中得以见到,二个service worker要经历以下进程:

  1.  安装

二.
 激活,激活成功未来,打开chrome://inspect/#service-workers能够查看到眼下运作的service
worker

图片 2

  1. 监听fetch和message事件,下边三种事件会进行简单描述

  2. 销毁,是或不是销毁由浏览器决定,借使多少个service
    worker长时间不行使依旧机器内部存款和储蓄器有数,则恐怕会销毁这一个worker

使用前的设置:

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

fetch事件

在页面发起http请求时,service
worker能够经过fetch事件拦截请求,并且付诸自个儿的响应。
w3c提供了多个新的fetch
api,用于代替XMLHttpRequest,与XMLHttpRequest最大不一致有两点:

一.
fetch()方法重返的是Promise对象,通过then方法开始展览延续调用,收缩嵌套。ES陆的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获取图片的例子,注释中详尽分解了每一步的作用:

JavaScript

/* 由于是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 fetch德姆o() { // 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); }); }
fetch德姆o();

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
4二发端扶助,对于旧浏览器,能够由此合法维护的polyfill扶助。

作用:

能够使你的施用先走访本地缓存能源,所以在离线状态时,在没有经过互连网收到到越来越多的数据前,还是可以提供基本的功力。

标题二. 权力太大

当service worker监听fetch事件随后,对应的伸手都会透过service
worker。通过chrome的network工具,能够见到此类请求会标注:from service
worker。如若service
worker中现身了难点,会招致全体请求战败,包罗一般的html文件。所以service
worker的代码品质、容错性一定要很好才能担保web app正常运作。

 

参照文章:

1. http://www.html5rocks.com/en/tutorials/service-worker/introduction/

2. http://www.sitepoint.com/introduction-to-the-fetch-api/

3. https://developer.mozilla.org/en-US/docs/Web/API/InstallEvent

4. https://developer.mozilla.org/en-US/docs/Web/API/ExtendableEvent

5. https://developer.mozilla.org/en-US/docs/Web/API/CacheStorage

1 赞 3 收藏
评论

图片 3

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图