serviceWorker

推荐阅读:Service Worker 简介

在 Service Worker 之前,我们一般用 AppCache 来实现离线体验(就是配置 Manifest 文件的方式),这个会有很多问题(博主曾尝试过,体验非常差,非常难用,而且不灵活)。

而 Service Worker 可以写脚本去灵活自由地控制缓存。

基本使用:

1. 注册

<!-- /report/index.html 片段 -->
<script>
    if (navigator.serviceWorker) {
        navigator.serviceWorker.register('./sw.js').then(res => {
            console.log('注册成功');
            // serviceWorker 是有作用域的,这里作用域是/report,如果是其他路径(例如/alarm)用到这个serviceWorker,它也不会工作。但是/report/**/* 都是可以生效的
            console.log('作用域是:' + res.scope);
        }).catch(e => {
            console.log('注册失败');
        })
    }
</script>

2. 安装

// /report/sw.js 片段
const CACHE_NAME = 'my-cache';
const cacheList = ['./index.html']
this.addEventListener('install', ev => {
    // waitUntil 传入 Promise,判断安装时间和成功与否
    ev.waitUntil(
        // 如果有则打开,不存在则创建这个 'my-cache' 缓存空间
        caches.open(CACHE_NAME).then(myCache => {
            // 往缓存里面存文件
            // return 出去形成 Promise 链,否则,caches.open 成功后, waitUntil 就以为已经安装成功了
            return myCache.addAll(cacheList);
        })
    )
})

3. 拦截请求并缓存

// /report/sw.js 片段
const CACHE_NAME = 'my-cache';

//....

this. addEventListener('fetch', ev => {
    // respondWith 传入一个 Promise,作为返回给页面的响应
    ev.respondWith(
        // 在所有缓存里面找是否有e.request的缓存
        caches.match(ev.request).then(res => {
            if (res) {
                return res;
            }
            return fetch(ev.request).then(res => {
                // 缓存的res需要先克隆,因为 res 会先 return 出去给页面使用,被使用后的 res 添加缓存会报错
                const resClone = res.clone();
                // 缓存新请求
                caches.open(CACHE_NAME).then(cache => {
                    cache.put(ev.request, resClone);
                })
                return res;
            })
        })
    )
})

不克隆,直接加入缓存会报错

 

posted @ 2019-08-28 09:16  张啊咩  阅读(467)  评论(0编辑  收藏  举报