Service Worker初体验美高梅娱乐场网站

发布时间:2019-02-20  栏目:计算机教程  评论:0 Comments

fetch()目前仅支持Service Workers

fetch马上支持在页面上使用了,但是目前的Chrome实现,它还只支持service
worker。cache
API也即将在页面上被支持,但是目前为止,cache也还只能在service
worker中用。

问题1. 运行时间

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,2,1,2,1,1,2….,原因是hitCounter并没有一直存在,如果浏览器关闭了它,下次启动的时候hitCounter就赋值为0了
这样的事情导致调试代码困难,当你更新一个service
worker以后,只有在打开新页面以后才可能使用新的service
worker,在调试过程中经常等上一两分钟才会使用新的,比较抓狂。

获得帮助

如果你遇到麻烦,请在Stackoverflow上发帖询问,使用‘service-worker’标签,以便于我们及时跟进和尽可能帮助你解决问题。

赞 2 收藏
评论

美高梅娱乐场网站 1

message事件

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

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

这里是一个小的页面之间通信demohttps://nzv3tos3n.qnssl.com/message/msg-demo.html

更多内容

这里有一些相关的文档可以参考:https://jakearchibald.github.io/isserviceworkerready/resources.html

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获取图片的例子,注释中详细解释了每一步的作用:

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 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();

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支持。

Service Worker的生命周期

Service worker拥有一个完全独立于Web页面的生命周期。

要让一个service
worker在你的网站上生效,你需要先在你的网页中注册它。注册一个service
worker之后,浏览器会在后台默默启动一个service worker的安装过程。

在安装过程中,浏览器会加载并缓存一些静态资源。如果所有的文件被缓存成功,service
worker就安装成功了。如果有任何文件加载或缓存失败,那么安装过程就会失败,service
worker就不能被激活(也即没能安装成功)。如果发生这样的问题,别担心,它会在下次再尝试安装。

当安装完成后,service
worker的下一步是激活,在这一阶段,你还可以升级一个service
worker的版本,具体内容我们会在后面讲到。

在激活之后,service
worker将接管所有在自己管辖域范围内的页面,但是如果一个页面是刚刚注册了service
worker,那么它这一次不会被接管,到下一次加载页面的时候,service
worker才会生效。

当service
worker接管了页面之后,它可能有两种状态:要么被终止以节省内存,要么会处理fetch和message事件,这两个事件分别产生于一个网络请求出现或者页面上发送了一个消息。

下图是一个简化了的service worker初次安装的生命周期:

美高梅娱乐场网站 2

问题2. 权限太大

当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

fetch()不遵循30x重定向规范

不幸,重定向在fetch()中不会被触发,这是当前版本的bug;

Service Worker初体验

2016/01/06 · JavaScript
· Service Worker

原文出处: AlloyTeam   

在2014年,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是如何工作的。

如何注册和安装service worker

要安装service
worker,你需要在你的页面上注册它。这个步骤告诉浏览器你的service
worker脚本在哪里。

JavaScript

美高梅娱乐场网站,if (‘serviceWorker’ in navigator) {
navigator.serviceWorker.register(‘/sw.js’).then(function(registration) {
// Registration was successful console.log(‘ServiceWorker registration
successful with scope: ‘, registration.scope); }).catch(function(err) {
// registration failed 🙁 console.log(‘ServiceWorker registration
failed: ‘, err); }); }

1
2
3
4
5
6
7
8
9
if (‘serviceWorker’ in navigator) {
  navigator.serviceWorker.register(‘/sw.js’).then(function(registration) {
    // Registration was successful
    console.log(‘ServiceWorker registration successful with scope: ‘,    registration.scope);
  }).catch(function(err) {
    // registration failed 🙁
    console.log(‘ServiceWorker registration failed: ‘, err);
  });
}

上面的代码检查service worker API是否可用,如果可用,service
worker /sw.js 被注册。

如果这个service worker已经被注册过,浏览器会自动忽略上面的代码。

有一个需要特别说明的是service
worker文件的路径,你一定注意到了在这个例子中,service
worker文件被放在这个域的根目录下,这意味着service
worker和网站同源。换句话说,这个service
work将会收到这个域下的所有fetch事件。如果我将service
worker文件注册为/example/sw.js,那么,service worker只能收到/example/路径下的fetch事件(例如: /example/page1/, /example/page2/)。

现在你可以到 chrome://inspect/#service-workers 检查service worker是否对你的网站启用了。

美高梅娱乐场网站 4

当service
worker第一版被实现的时候,你也可以在chrome://serviceworker-internals中查看,它很有用,通过它可以最直观地熟悉service worker的生命周期,不过这个功能很快就会被移到chrome://inspect/#service-workers中。

你会发现这个功能能够很方便地在一个模拟窗口中测试你的service
worker,这样你可以关闭和重新打开它,而不会影响到你的新窗口。任何创建在模拟窗口中的注册服务和缓存在窗口被关闭时都将消失。

生命周期

先来看一下一个service worker的运行周期

美高梅娱乐场网站 5
上图是service
worker生命周期,出处http://www.html5rocks.com/en/tutorials/service-worker/introduction/

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

  1.  安装

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

美高梅娱乐场网站 6

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

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

处理响应式图片

img的srcset属性或者<picture>标签会根据情况从浏览器或者网络上选择最合适尺寸的图片。

在service worker中,你想要在install步骤缓存一个图片,你有以下几种选择:

  1. 安装所有的<picture>元素或者将被请求的srcset属性。
  2. 安装单一的low-res版本图片
  3. 安装单一的high-res版本图片

比较好的方案是2或3,因为如果把所有的图片都给下载下来存着有点浪费内存。

假设你将low-res版本在install的时候缓存了,然后在页面加载的时候你想要尝试从网络上下载high-res的版本,但是如果high-res版本下载失败的话,就依然用low-res版本。这个想法很好也值得去做,但是有一个问题:

如果我们有下面两种图片:

Screen Density Width Height
1x 400 400
2x 800 800

HTML代码如下:

JavaScript

<img src=”image-src.png” srcset=”image-src.png 1x, image-2x.png 2x”
/>

1
<img src="image-src.png" srcset="image-src.png 1x, image-2x.png 2x" />

如果我们在一个2x的显示模式下,浏览器会下载image-2x.png,如果我们离线,你可以读取之前缓存并返回image-src.png替代,如果之前它已经被缓存过。尽管如此,由于现在的模式是2x,浏览器会把400X400的图片显示成200X200,要避免这个问题就要在图片的样式上设置宽高。

JavaScript

<img src=”image-src.png” srcset=”image-src.png 1x, image-2x.png 2x”
style=”width:400px; height: 400px;” />

1
2
<img src="image-src.png" srcset="image-src.png 1x, image-2x.png 2x"
style="width:400px; height: 400px;" />

美高梅娱乐场网站 7

<picture>标签情况更复杂一些,难度取决于你是如何创建和使用的,但是可以通过与srcset类似的思路去解决。

利用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是一个InstallEvent对象,继承自ExtendableEvent,其中的waitUntil()方法接收一个promise对象,直到这个promise对象成功resolve之后,才会继续运行service-worker.js。
caches是一个CacheStorage对象,使用open()方法打开一个缓存,缓存通过名称进行区分。
获得cache实例之后,调用addAll()方法缓存文件。

这样就将文件添加到caches缓存中了,想让浏览器使用缓存,还需要拦截fetch事件

JavaScript

// 缓存图片 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; }); }) ) });

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的过程中,也遇到了一些问题,下面是其中两个

如果安装失败了,没有很优雅的方式获得通知

如果一个worker被注册了,但是没有出现在chrome://inspect/#service-workers或chrome://serviceworker-internals,那么很可能因为异常而安装失败了,或者是产生了一个被拒绝的的promise给event.waitUtil。

要解决这类问题,首先到 chrome://serviceworker-internals检查。打开开发者工具窗口准备调试,然后在你的install event代码中添加debugger;语句。这样,通过断点调试你更容易找到问题。

Service Worker的安装步骤

在页面上完成注册步骤之后,让我们把注意力转到service
worker的脚本里来,在这里面,我们要完成它的安装步骤。

在最基本的例子中,你需要为install事件定义一个callback,并决定哪些文件你想要缓存。

JavaScript

// The files we want to cache var urlsToCache = [ ‘/’,
‘/styles/main.css’, ‘/script/main.js’ ]; // Set the callback for the
install step self.addEventListener(‘install’, function(event) { //
Perform install steps });

1
2
3
4
5
6
7
8
9
10
11
// The files we want to cache
var urlsToCache = [
  ‘/’,
  ‘/styles/main.css’,
  ‘/script/main.js’
];
 
// Set the callback for the install step
self.addEventListener(‘install’, function(event) {
    // Perform install steps
});

在我们的install callback中,我们需要执行以下步骤:

  1. 开启一个缓存
  2. 缓存我们的文件
  3. 决定是否所有的资源是否要被缓存

JavaScript

var CACHE_NAME = ‘my-site-cache-v1’; var urlsToCache = [ ‘/’,
‘/styles/main.css’, ‘/script/main.js’ ];
self.addEventListener(‘install’, function(event) { // Perform install
steps event.waitUntil( caches.open(CACHE_NAME) .then(function(cache) {
console.log(‘Opened cache’); return cache.addAll(urlsToCache); }) ); });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var CACHE_NAME = ‘my-site-cache-v1’;
var urlsToCache = [
  ‘/’,
  ‘/styles/main.css’,
  ‘/script/main.js’
];
 
self.addEventListener(‘install’, function(event) {
  // Perform install steps
  event.waitUntil(
    caches.open(CACHE_NAME)
      .then(function(cache) {
        console.log(‘Opened cache’);
        return cache.addAll(urlsToCache);
      })
  );
});

上面的代码中,我们通过caches.open打开我们指定的cache文件名,然后我们调用cache.addAll并传入我们的文件数组。这是通过一连串promise(caches.open

cache.addAll)完成的。event.waitUntil拿到一个promise并使用它来获得安装耗费的时间以及是否安装成功。

如果所有的文件都被缓存成功了,那么service
worker就安装成功了。如果任何一个文件下载失败,那么安装步骤就会失败。这个方式允许你依赖于你自己指定的所有资源,但是这意味着你需要非常谨慎地决定哪些文件需要在安装步骤中被缓存。指定了太多的文件的话,就会增加安装失败率。

上面只是一个简单的例子,你可以在install事件中执行其他操作或者甚至忽略install事件。

Service Worker 是什么?

一个 service worker
是一段运行在浏览器后台进程里的脚本,它独立于当前页面,提供了那些不需要与web页面交互的功能在网页背后悄悄执行的能力。在将来,基于它可以实现消息推送,静默更新以及地理围栏等服务,但是目前它首先要具备的功能是拦截和处理网络请求,包括可编程的响应缓存管理。

为什么说这个API是一个非常棒的API呢?因为它使得开发者可以支持非常好的离线体验,它给予开发者完全控制离线数据的能力。

在service worker提出之前,另外一个提供开发者离线体验的API叫做App
Cache。然而App
Cache有些局限性,例如它可以很容易地解决单页应用的问题,但是在多页应用上会很麻烦,而Service
workers的出现正是为了解决App Cache的痛点。

下面详细说一下service worker有哪些需要注意的地方:

  • 它是JavaScript
    Worker
    ,所以它不能直接操作DOM。但是service
    worker可以通过postMessage与页面之间通信,把消息通知给页面,如果需要的话,让页面自己去操作DOM。
  • Service
    worker是一个可编程的网络代理,允许开发者控制页面上处理的网络请求。
  • 在不被使用的时候,它会自己终止,而当它再次被用到的时候,会被重新激活,所以你不能依赖于service
    worker的onfecth和onmessage的处理函数中的全局状态。如果你想要保存一些持久化的信息,你可以在service
    worker里使用IndexedDB API。
  • Service
    worker大量使用promise,所以如果你不了解什么是promise,那你需要先阅读这篇文章。

留下评论

网站地图xml地图