Javascript ServiceWorker缓存不稳定

Javascript ServiceWorker缓存不稳定,javascript,service-worker,Javascript,Service Worker,好的,我只是从服务人员开始 我的sw.js中有以下代码: const cacheName = "v2" // Call Install Event self.addEventListener('install', function (e) { console.log('Service Worker: Installed') }) // Call Activate Event self.addEventListener('activate', function (e) { c

好的,我只是从服务人员开始

我的
sw.js
中有以下代码:

const cacheName = "v2"

// Call Install Event
self.addEventListener('install', function (e) {
    console.log('Service Worker: Installed')

})

// Call Activate Event
self.addEventListener('activate', function (e) {
    console.log('Service Worker: Activated')

    // Remove unwanted caches
    e.waitUntil(
        caches.keys().then(cacheNames => {
            return Promise.all(
                cacheNames.map(cache => {
                    if(cache != cacheName) {
                        console.log('Service Worker: Clearing Old Cache')
                        return caches.delete(cache)
                    }   
                })
            )
        })
    )
})


self.addEventListener('fetch', function (e) {
    console.log("Service Worker: Fetch")

    // var url = new URL(e.request.url)
    // console.log("Fetch page: " + url)

    e.respondWith(
        //fetch(e.request).catch(() => caches.match(e.request))
        fetch(e.request)
        .then(res => {
            // Make copy/clone of response
            const responseClone = res.clone()

            // Open Cache
            caches
            .open(cacheName)
            .then(cache => {
                // Add response to cache
                cache.put(e.request, responseClone)
            })
            return response
        }).catch(err => caches.match(e.request).then(res => res))
    )

})
我几乎是从youtube视频中复制的。现在,我的测试站点使用了许多CDN、样式表和javascript文件。有些是内部的,有些是外部的。以下是我在控制台中收到的错误列表:

5sw.js:30 Service Worker: Fetch
5The FetchEvent for "<URL>" resulted in a network error response: an object that was not a Response was passed to respondWith().
The FetchEvent for "https://labs.domain.net/styles.css" resulted in a network error response: an object that was not a Response was passed to respondWith().
Promise.then (async)
(anonymous) @ sw.js:35
The FetchEvent for "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" resulted in a network error response: an object that was not a Response was passed to respondWith().
Promise.then (async)
(anonymous) @ sw.js:35
The FetchEvent for "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" resulted in a network error response: an object that was not a Response was passed to respondWith().
Promise.then (async)
(anonymous) @ sw.js:35
The FetchEvent for "https://labs.domain.net/javascript.js" resulted in a network error response: an object that was not a Response was passed to respondWith().
Promise.then (async)
(anonymous) @ sw.js:35
The FetchEvent for "https://code.jquery.com/jquery-3.2.1.slim.js" resulted in a network error response: an object that was not a Response was passed to respondWith().
Promise.then (async)
(anonymous) @ sw.js:35
index.php:7 GET https://labs.domain.net/styles.css net::ERR_FAILED
index.php:9 GET https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css net::ERR_FAILED
index.php:11 GET https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js net::ERR_FAILED
index.php:45 GET https://labs.domain.net/javascript.js net::ERR_FAILED
index.php:10 GET https://code.jquery.com/jquery-3.2.1.slim.js net::ERR_FAILED
5sw.js:30服务人员:获取
5“”的FetchEvent导致网络错误响应:将不是响应的对象传递给respondWith()。
“的获取事件”https://labs.domain.net/styles.css“导致网络错误响应:将不是响应的对象传递给respondWith()。
Promise.then(异步)
(匿名)@sw.js:35
“的获取事件”https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css“导致网络错误响应:将不是响应的对象传递给respondWith()。
Promise.then(异步)
(匿名)@sw.js:35
“的获取事件”https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js“导致网络错误响应:将不是响应的对象传递给respondWith()。
Promise.then(异步)
(匿名)@sw.js:35
“的获取事件”https://labs.domain.net/javascript.js“导致网络错误响应:将不是响应的对象传递给respondWith()。
Promise.then(异步)
(匿名)@sw.js:35
“的获取事件”https://code.jquery.com/jquery-3.2.1.slim.js“导致网络错误响应:将不是响应的对象传递给respondWith()。
Promise.then(异步)
(匿名)@sw.js:35
php:7gethttps://labs.domain.net/styles.css net::ERR_失败
php:9gethttps://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css net::ERR_失败
php:11获取https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js net::ERR_失败
php:45获取https://labs.domain.net/javascript.js net::ERR_失败
php:10gethttps://code.jquery.com/jquery-3.2.1.slim.js net::ERR_失败
我不明白。当我点击它声明失败的链接时,它会在浏览器中正确加载,我可以看到它的内容。标签为“labs.domain.net”的文件位于我的服务器上,并且托管在sw.js文件的旁边。它们也可以正确加载。但出于某种原因,服务人员抛出了所有这些错误

如果我在每个页面加载之前点击页面(我有三个,index.php,about.php和jimmeny.php),我会收到一条“此网站无法访问”的消息,然后页面会在几秒钟后加载


有人能给我指出正确的方向,指出我的错误所在吗?我的网站非常简单,我不明白为什么资源不能正确保存。

我只想给你发一条评论,但是版主把一个朋友赶了出去,因为他在这里有一段时间没有登录,这只是用了我的一点声誉来阻止我评论。抱怨够了

只是想让你知道,你应该考虑和服务人员缓存什么资源。您需要实现最适合您正在构建的应用程序的缓存控制策略

此外,每次service worker安装新版本时,这并不一定意味着您从新缓存开始,缓存可以独立于service worker变体进行管理。我建议您开始同时使用版本化缓存和服务工作者。这样你就能更好地控制局面。缓存绝对是稳定的

要检查您当前为Chrome缓存了哪些资源,请转到: 开发人员工具(Ctrl+Shift+I)->应用程序(选项卡)->缓存->缓存存储(从侧菜单展开)您应该会看到“缓存的名称”,一旦选择“感兴趣的缓存名称”-“v2”,您应该会确切地看到您在查看时缓存了哪些资源

另外,尝试只缓存您可以控制的资源。Ie不是来自第三方,因为可能有一些问题需要调查。请记住,如果您的服务人员没有控制第三方资源,您就不能指望它能够处理这些资源。该服务工作人员在其放置的域名上的当前位置下有一个作用域

如果要在发布新版本的service worker之前永久添加service worker控制范围内的资源,可以使用以下方法:

self.addEventListener('fetch', event => {
    if (event.request.method === 'GET') { //only bother for static resources ;)
        switch (0) {
            case event.request.url.indexOf('https://www.google-analytics.com'):
            case event.request.url.indexOf('https://www.googletagmanager.com'):
                // skip adding to cache
                // console.warn('skip adding to cache ' + event.request.method + ' ' + event.request.mode + ' ' + event.request.url);
            break;
            case event.request.url.indexOf(SERVER_URL):
                // Cache falling back to network
                // console.info('[PWA] The service worker is serving an asset. ' + event.request.method + ' ' + event.request.mode + ' ' + event.request.url);
                event.respondWith(
                    caches.open(CACHE_NAME).then((cache) => {
                        return cache.match(event.request).then((response) => {
                            return response || fetch(event.request).then((response) => {
                                if (response.status === 200) {
                                    cache.put(event.request, response.clone());
                                    return response;
                                } else if (response.type === 'opaqueredirect' || response.status === 404) {
                                    return response;
                                } else {
                                    return cache.match('offline.html');
                                }
                            }).catch(() => {
                                return cache.match('offline.html');
                            });
                        });
                    })
                );
            break;
            default:
            // console.warn('new case for cache ' + event.request.method + ' ' + event.request.mode + ' ' + event.request.url);
        }
    }
});
在本例中,您应该在安装软件时缓存“offline.html”,以便在用户尝试在脱机时访问资源而该资源以前未缓存时显示它。该方法可以描述为“服务缓存或从网络中获取资源,然后从缓存中服务”。您还需要通过发布新的service worker变体来实现修剪/替换/更新静态资源缓存的逻辑,并在需要时执行此逻辑


干杯

请注意,由于后端能够提供动态内容,测试(event.request.method==“GET”)不能保证资源是静态的。这一切都取决于你的情况,你应该相应地计划。谢谢你。但我仍然无法理解为什么它在某些资源上失败,而不是在所有资源上失败。你对此有什么解释吗?它们是指向我的服务器上或外部文件的有效URL,由于某些原因,我无法确定它们是否失败。我知道你提供的代码阻止了这一点,我会使用它,但我不喜欢我无法解释的东西!不同的资源可能会因不同的原因而失败,您只需深入挖掘,例如,当浏览器获得重定向时,浏览器将知道如何处理它,但您的软件将需要指示如何操作!另一个更复杂的原因是,当您向一个文件发送请求时,它会通知您获取