Service Worker从缓存中获取请求,因此页面不会从新数据中更新 [英] Service Worker fetch request from cache so page is not getting updated from new data

查看:288
本文介绍了Service Worker从缓存中获取请求,因此页面不会从新数据中更新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在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))
            );
        }
    }
});

解决方案

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

I am trying to implement the service worker in my AngularJS project for the purpose that if the server(nginx in my case) is restarted then offline page must be displayed for that period but I stuck in the other case.

I have a page where I list the items using GET request, it's fetching response from the server (for the 1 st time), response data being stored in cache BUT my page is updating within regular interval so using this technique the new data are not displaying immediately.

What is wrong in this approach, kindly suggest the better way.

folder structure

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

below is the code of my service worker file

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

解决方案

Your key for the resource in cache is request (Since you are using cache.put(request, copy) in addToCache function), but you are retrieving it using url (e.g /offline.html in offlineResponse function). You should match with request in cache.

这篇关于Service Worker从缓存中获取请求,因此页面不会从新数据中更新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆