首页 文章

Service Worker从缓存获取请求,因此页面不会从新数据更新

提问于
浏览
0

我正在尝试在我的AngularJS项目中实现服务工作者,目的是如果服务器(在我的情况下是nginx)重新启动,那么必须在那段时间显示离线页面,但我坚持在另一种情况下 .

我有一个页面,我使用GET请求列出项目,它从服务器获取响应(第一次),响应数据存储在缓存中但是我的页面在定期间隔内更新,所以使用这种技术新数据不是立即显示 .

这种方法有什么问题,请提出更好的方法 .

文件夹结构

.
├── app
├── assets
├── favicon.ico
├── index.html
├── libs
├── offline.html
└── sw.js

下面是我的服务工作者文件的代码

sw.js

'use strict';

let appCaches = [{
    name: 'static',
    urls: [
        '/app/',
        '/'
    ]
}, {
    name: 'offline',
    urls: [
        '/offline.html'
    ]
}];

let cacheNames = appCaches.map((cache) => cache.name);

self.addEventListener("install", (event) => {
    // console.log('installing');
    event.waitUntil(
        caches.keys()
        .then((keys) => {
            return Promise.all(appCaches.map((appCache) => {
                console.log(`cache Name:: ${appCache.name}`);
                console.log(`keys:: ${keys}`);
                if (keys.indexOf(appCache.name) === -1) {
                    caches.open(appCache.name).then((cache) => {
                        console.log(`caching ${appCache.name}`);
                        return cache.addAll(appCache.urls);
                    });
                } else {
                    console.log(`found ${appCache.name}`);
                    return Promise.resolve(true);
                }
            })).then(function() {
                // At this point everything has been cached
                return self.skipWaiting();
            });
        }));
});


//Adding `activate` event listener
self.addEventListener('activate', (event) => {
    // console.info('Event: Activate');
    //Remove old and unwanted caches
    event.waitUntil(
        caches.keys().then((keys) => {
            return Promise.all(keys.map((key) => {
                console.log(`activation checking key ${key}`);
                if (cacheNames.indexOf(key) === -1) {
                    console.log(`deleting ${key}`);
                    return caches.delete(key);
                }
            }));
        })
    );
});

//-------------------------------------------------------------------
function addToCache(cacheKey, request, response) {
    console.log("addToCache", arguments);
    if (response.ok) {
        var copy = response.clone();
        caches.open(cacheKey).then((cache) => {
            cache.put(request, copy);
        });
        return response;
    }
}

function fetchFromCache(event) {
    console.log("fetchFromCache", arguments);
    return caches.match(event.request).then((response) => {
        if (!response) {
            // A synchronous error that will kick off the catch handler
            throw Error('${event.request.url} not found in cache');
        }
        return response;
    });
}

function offlineResponse(resourceType) {
    console.log("%c offlineResponse::resourceType::" + resourceType, 'color:green');
    if (resourceType === 'content') {
        return caches.match('/offline.html');
    }
    return undefined;
}

self.addEventListener('fetch', (event) => {
    var request = event.request;
    var url = new URL(request.url);
    console.log("%curl=>" + url, 'color:red');
    var acceptHeader = request.headers.get('Accept');
    var resourceType = 'static';
    var cacheKey;

    if (acceptHeader.indexOf('text/html') !== -1) {
        resourceType = 'content';
    } else if (acceptHeader.indexOf('image') !== -1) {
        resourceType = 'image';
    }

    // {String} [static|image|content]
    cacheKey = resourceType;

    if (request.method !== 'GET') {
        return;
    } else {
        console.log("resourceType=>", cacheKey);
        if (resourceType === 'content') {
            // Use a network-first strategy.
            console.info("Use a network-first strategy.");
            event.respondWith(
                fetch(request)
                .then((response) => addToCache(cacheKey, request, response))
                .catch(() => fetchFromCache(event))
                .catch(() => offlineResponse(resourceType))
            );
        } else {
            // Use a cache-first strategy.
            console.info("Use a cache-first strategy.");
            event.respondWith(
                fetchFromCache(event)
                .catch(() => fetch(request))
                .then((response) => addToCache(cacheKey, request, response))
                .catch(() => offlineResponse(resourceType))
            );
        }
    }
});

1 回答

  • 1

    您的 key 用于缓存中的资源是 request (因为您在 addToCache 函数中使用了 cache.put(request, copy) ),但是您正在使用 url (例如 offlineResponse 函数中的 /offline.html )进行检索 . 您应该与 cache 中的 request 匹配 .

相关问题