连不上网

作者: 前端技术  发布:2019-11-03

Service Worker初体验

2016/01/06 · JavaScript · Service Worker

最早的作品出处: AlloyTeam   

在二零一五年,W3C发布了service worker的草案,service worker提供了非常多新的技艺,使得web app拥有与native app相符的离线体验、新闻推送体验。
service worker是少年老成段脚本,与web worker相仿,也是在后台运营。作为一个独自的线程,运营条件与日常脚本分裂,所以无法直接参加web交互行为。native app能够变成离线使用、音信推送、后台自动更新,service worker的现身是多亏为了使得web app也得以有所相仿的力量。

 

service worker可以:

  1. 后台音讯传递
  2. 网络代理,转载呼吁,诬捏响应
  3. 离线缓存
  4. 信息推送
  5.  … …

本文以能源缓存为例,说圣元下service worker是怎么着行事的。

连不上网?United Kingdom卫报的天性离线页面是这么做的

2015/11/20 · HTML5 · Service Worker, 离线页面

本文由 伯乐在线 - Erucy 翻译,weavewillg 校稿。未经许可,禁绝转发!
德语出处:Oliver Ash。迎接参与翻译组。

大家是什么样运用 service worker 来为 theguardian.com 创设八个自定义的离线页面。

图片 1

theguardian.com 的离线页面。插图:奥利弗 Ash

你正在朝着集团途中的地铁里,在手提式有线电话机上开荒了 Guardian 应用。大巴被隧道包围着,可是这几个利用能够健康运维,固然未有互连网连接,你也能赢得完全的意义,除了出示的内容只怕有一点点旧。假如你品味在网址上也如此干,可惜它完全无法加载:

图片 2

安卓版 Chrome 的离线页面

Chrome 中的这些彩蛋,很几人都不明白》

Chrome 在离线页面上有个藏匿的游玩(桌面版上按空格键,手提式无线电话机版上点击那只恐龙卡塔 尔(英语:State of Qatar),那有一点能缓慢解决一点您的忧虑。可是大家能够做得更加好。

Service workers 允许网址小编拦截自个儿站点的保有互连网央浼,那也就代表大家可以提供周密的离线体验,就像原生应用雷同。在 Guardian 网址,大家近些日子上线了三个自定义的离线体验效果。当客户离线的时候,他们拜谒到三个包涵Guardian 标识的页面,上边带有一个轻巧易行的离线提醒,还也许有二个填字游戏,他们能够在等候网络连接的时候玩玩那几个找点乐子。那篇博客解释了我们是何等营造它的,不过在起来早先,你能够先自个儿试试看。

生命周期

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

图片 3
上海教室是service worker生命周期,出处

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

  1.  安装

2.  激活,激活成功之后,张开chrome://inspect/#service-workers可以查阅到这段日子运营的service worker

图片 4

  1. 监听fetch和message事件,下边二种事件博览会开简要描述

  2. 销毁,是或不是销毁由浏览器决定,借使一个service worker长期不选择依然机器内部存储器有数,则大概会销毁那几个worker

试试看

您要求一个支撑 Service Worker 和 fetch API 的浏览器。停止到本文编写时只有Chrome(手提式有线电话机版和桌面版卡塔 尔(英语:State of Qatar)同不常候辅助那二种 API(译者注:Opera 近年来也帮助那五头卡塔尔,然则 Firefox 异常快将在支持了(在每日更新的本子中曾经帮助了卡塔 尔(阿拉伯语:قطر‎,除此之外 Safari 之外的装有浏览器也都在实践。其他,service worker 只好登记在行使了 HTTPS 的网址上,theguardian.com 已经开端逐步搬迁到 HTTPS,所以大家只可以在网址的 HTTPS 部分提供离线体验。就近年来以来,大家接收了 开拓者博客 作为我们用来测量检验的地方。所以大器晚成旦你是在大家网址的 开垦者博客 部分阅读那篇文章的话,很幸运。

当您利用扶持的浏览器访谈我们的 开辟者博客 中的页面包车型大巴时候,一切就计划稳当了。断开你的网络连接,然后刷新一下页面。若是您本人没标准尝试的话,能够看一下这段 示范摄像(译者注:需梯子)。

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的黄金年代处接受。

下边是在中,小编运用fetch api通过fliker的了然api获取图片的例证,注释中详尽解释了每一步的机能:

JavaScript

/* 由于是get伏乞,直接把参数作为query string传递了 */ var URL = ''; function fetch德姆o() { // fetch(url, option)协理四个参数,option中得以设置header、body、method音信fetch(UKoleosL).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 42起来协助,对于旧浏览器,能够透过法定维护的polyfill协助。

行事规律

透过少年老成段轻易的 JavaScript,大家得以提示浏览器在客户访谈页面的时候立刻登记大家本身的 service worker。前段时间匡助 service worker 的浏览器少之甚少,所认为了防止不当,大家需求使用特性检查实验。

JavaScript

if (navigator.serviceWorker) { navigator.serviceWorker.register('/service-worker.js'); }

1
2
3
if (navigator.serviceWorker) {
    navigator.serviceWorker.register('/service-worker.js');
}

Service worker 安装事件的黄金时代有些,我们得以选取 新的缓存 API 来缓存大家网址中的各样内容,比方 HTML、CSS 和 JavaScript:

JavaScript

var staticCacheName = 'static'; var version = 1; function updateCache() { return caches.open(staticCacheName + version) .then(function (cache) { return cache.addAll([ '/offline-page.html', '/assets/css/main.css', '/assets/js/main.js' ]); }); }; self.addEventListener('install', function (event) { event.waitUntil(updateCache()); });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var staticCacheName = 'static';
var version = 1;
 
function updateCache() {
    return caches.open(staticCacheName + version)
        .then(function (cache) {
            return cache.addAll([
                '/offline-page.html',
                '/assets/css/main.css',
                '/assets/js/main.js'
            ]);
        });
};
 
self.addEventListener('install', function (event) {
    event.waitUntil(updateCache());
});

当安装到位后,service worker 能够监听和调整 fetch 事件,让我们得以完全调整之后网址中发生的具备互连网恳求。

JavaScript

self.addEventListener('fetch', function (event) { event.respondWith(fetch(event.request)); });

1
2
3
self.addEventListener('fetch', function (event) {
    event.respondWith(fetch(event.request));
});

在此我们有很利索的空间能够发挥,举例下边这一个点子,能够透过代码来生成大家和睦的伸手响应:

JavaScript

self.addEventListener('fetch', function (event) { var response = new Response('<h1>Hello, World!</h1>', { headers: { 'Content-Type': 'text/html' } }); event.respondWith(response); });

1
2
3
4
5
self.addEventListener('fetch', function (event) {
    var response = new Response('&lt;h1&gt;Hello, World!&lt;/h1&gt;',
        { headers: { 'Content-Type': 'text/html' } });
    event.respondWith(response);
});

再有那几个,固然在缓存中找到了哀告相应的缓存,大家能够直接从缓存中回到它,即使没找到的话,再通过互联网拿到响应内容:

JavaScript

self.addEventListener('fetch', function (event) { event.respondWith( caches.match(event.request) .then(function (response) { return response || fetch(event.request); }) ); });

1
2
3
4
5
6
7
8
self.addEventListener('fetch', function (event) {
    event.respondWith(
        caches.match(event.request)
            .then(function (response) {
                return response || fetch(event.request);
            })
    );
});

那正是说大家怎么样利用那么些意义来提供离线体验吧?

先是,在 service worker 安装进程中,大家必要把离线页面必要的 HTML 和财富文件通过 service worker 缓存下来。在缓存中,我们加载了温馨费用的 填字游戏 的 React应用 页面。之后,我们会阻拦全数访问theguardian.com 网络恳求,包蕴网页、以致页面中的财富文件。管理那些诉求的逻辑大概如下:

  1. 当大家检查实验到传播央浼是指向大家的 HTML 页面时,大家连年会想要提供最新的故事情节,所以大家会尝试把那么些央求通过网络发送给服务器。
    1. 当大家从服务器得到了响应,就足以一贯再次来到这些响应。
    2. 若果互联网央浼抛出了丰硕(比方因为客户掉线了卡塔尔国,大家捕获这几个极其,然后使用缓存的离线 HTML 页面作为响应内容。
  2. 要不,当我们检验到央求的不是 HTML 的话,大家会从缓存中追寻响应的乞请内容。
    1. 只要找到了缓存内容,我们可以直接重回缓存的始末。
    2. 要不然,大家会尝试把这么些供给通过网络发送给服务器。

在代码中,大家选取了 新的缓存 API(它是 Service Worker API 的生龙活虎部分卡塔 尔(英语:State of Qatar)以致 fetch 功效(用于转移互联网供给卡塔 尔(阿拉伯语:قطر‎,如下所示:

JavaScript

var doesRequestAcceptHtml = function (request) { return request.headers.get('Accept') .split(',') .some(function (type) { return type === 'text/html'; }); }; self.addEventListener('fetch', function (event) { var request = event.request; if (doesRequestAcceptHtml(request)) { // HTML pages fallback to offline page event.respondWith( fetch(request) .catch(function () { return caches.match('/offline-page.html'); }) ); } else { // Default fetch behaviour // Cache first for all other requests event.respondWith( caches.match(request) .then(function (response) { return response || fetch(request); }) ); } });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var doesRequestAcceptHtml = function (request) {
    return request.headers.get('Accept')
        .split(',')
        .some(function (type) { return type === 'text/html'; });
};
 
self.addEventListener('fetch', function (event) {
    var request = event.request;
    if (doesRequestAcceptHtml(request)) {
        // HTML pages fallback to offline page
        event.respondWith(
            fetch(request)
                .catch(function () {
                    return caches.match('/offline-page.html');
                })
        );
    } else {
        // Default fetch behaviour
        // Cache first for all other requests
        event.respondWith(
            caches.match(request)
                .then(function (response) {
                    return response || fetch(request);
                })
        );
    }
});

就只须要如此多!theguardian.com 上的 持有代码都以在 GitHub 上开源 的,所以您能够去那儿查看大家的 service worker 的欧洲经济共同体版本,大概直接从生产情况上访谈 。

小编们有充裕的说辞为那些新的浏览器工夫欢呼喝彩,因为它能够用来让您的网址像后日的原生应用近似,具有完美的离线体验。今后当 theguardian.com 完全迁移到 HTTPS 之后,离线页面包车型客车基本点性会鲜明增加,我们能够提供更为周密的离线体验。捏造一下你在上下班途中网络比较糟糕的时候访谈theguardian.com,你会看出专门为您订制的特性化内容,它们是在你从前访谈网址时由浏览器缓存下来的。它在设置进程中也不会时有产生其余困难,你所供给的只是访谈这些网址而已,不像原生应用,还须求客商有贰个选拔集团的账号技术安装。Serviceworker 相通能够扶助大家升高网站的加载速度,因为网址的框架能够被保障地缓存下来,就像是原生应用相仿。

豆蔻梢头经您对 service worker 很感兴趣,想要精晓越多内容的话,开荒者 MattGaunt(Chrome的鞠躬尽瘁扶持者卡塔 尔(英语:State of Qatar)写了大器晚成篇尤其详实地 介绍 Service Worker的文章。

打赏扶持作者翻译更多好文章,感谢!

打赏译者

message事件

页面和serviceWorker之间能够因而posetMessage()方法发送消息,发送的新闻可以经过message事件接纳到。

这是多个双向的长河,页面能够发音讯给service worker,service worker也能够发送音信给页面,由于这一个特点,可以将service worker作为中间纽带,使得三个域名依然子域名下的多个页面能够随意通信。

这里是一个小的页面之间通讯demo

打赏扶持作者翻译更加多好小说,多谢!

图片 5

1 赞 收藏 评论

应用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代码。
依照前边的生命周期图,在三个新的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是二个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起到了二个在那之中代理的功用。

service worker央浼的进度通过fetch api达成,获得response对象以后举办过滤,查看是或不是是图片文件,假诺不是,就径直再次回到央浼,不会缓存。

如固然图形,要先复制豆蔻梢头份response,原因是request或然response对象归于stream,只可以接收二次,之后大器晚成份存入缓存,另风流浪漫份发送给页面。
那正是service worker的不战而屈人之兵之处:拦截供给,杜撰响应。fetch api在那也起到了超级大的出力。

 

service worker的纠正极粗略,只要service-worker.js的文本内容有修正,就还可以新的本子。可是有有些要细心:旧缓存文件的杀绝、新文件的缓存要在activate事件中打开,因为只怕旧的页面还在利用早先的缓存文件,解除之后会失掉功能。

 

在第生机勃勃使用service worker的进程中,也蒙受了有的标题,下边是中间多少个

关于作者:Erucy

图片 6

早已的SharePoint喵星技师(暂且还挂着微软MVP的名头卡塔尔,未来的Azure/.Net/MongoDB/Cordova/前端程序猿,一时写小说 个人主页 · 小编的文章 · 46 ·   

图片 7

难题1. 运作时刻

service worker并不是直接在后台运营的。在页面关闭后,浏览器能够一而再再而三保证service worker运转,也足以关闭service worker,那取决与浏览器自身的表现。所以实际不是定义一些全局变量,比方上边包车型客车代码(来自):

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,2,1,2,1,1,2….,原因是hitCounter并从未直接存在,假设浏览器关闭了它,后一次起动的时候hitCounter就赋值为0了
那般的事体导致调节和测量检验代码困难,当你更新一个service worker现在,只有在开发新页面以往才恐怕利用新的service worker,在调治进度中有时等上黄金年代两分钟才会使用新的,比较抓狂。

主题材料2. 权力太大

当service worker监听fetch事件以往,对应的伸手都会通过service worker。通过chrome的network工具,能够看看此类乞求会注脚:from service worker。倘若service worker中现身了难点,会变成全部恳求战败,包罗日常的html文件。所以service worker的代码品质、容错性一定要很好技巧承保web app符合规律运作。

 

参照他事他说加以考察文章:

1. 

2. 

3. 

4. 

5. 

1 赞 3 收藏 评论

图片 8

本文由金沙澳门官网送注册58发布于前端技术,转载请注明出处:连不上网

关键词: