【问题标题】:Javascript service worker: Fetch resource from cache, but also update itJavascript服务工作者:从缓存中获取资源,但也更新它
【发布时间】:2017-01-14 19:03:19
【问题描述】:

我在 chrome 上使用 service worker 来缓存网络响应。当客户请求资源时我打算做什么:

检查缓存 - 如果存在,则从缓存返回,但如果文件与缓存版本不同,也会向服务器发送请求并更新缓存。 如果缓存没有,向服务器发送请求,然后缓存响应。

这是我当前执行相同操作的代码:

self.addEventListener('fetch', function (event) {
    var requestURL = new URL(event.request.url);
    var freshResource = fetch(event.request).then(function (response) {
        if (response.ok && requestURL.origin === location.origin) {
            // All good? Update the cache with the network response
            caches.open(CACHE_NAME).then(function (cache) {
                cache.put(event.request, response);
            });
        }
        // Return the clone as the response would be consumed while caching it
        return response.clone();
    });
    var cachedResource = caches.open(CACHE_NAME).then(function (cache) {
        return cache.match(event.request);
    });
    event.respondWith(cachedResource.catch(function () {
        return freshResource;
    }));
});

此代码不起作用,因为它会引发错误:

url 的 FetchEvent 导致网络错误响应:一个不是 Response 的对象被传递给了 respondWith()。

谁能指出我正确的方向?

【问题讨论】:

  • catch 实际上返回一个 Promise 对象。您可能希望将then 处理程序附加到cachedResource 并在其中调用respondWith
  • @thefourtheye - 你的意思是,在then 中为cache.match 调用event.respondWith?这将是一个错误,因为 fetch 将在执行 caches.open 时解决。我进行了更改并运行代码以找到此错误。
  • @Awol:怎么会这样?大概是缓存打开和匹配比获取更快?
  • @Bergi - Fetch 确实比打开缓存需要更多时间,但event.respondWith 在caches.open 内部被触发,在fetch 处理程序结束后触发
  • 好的,伙计们。我解决了我的问题并发布了答案。非常感谢您的想法!

标签: javascript caching promise service-worker


【解决方案1】:

好的,在人们指出建议(谢谢)并找到解决方案后,我修改了代码。

self.addEventListener('fetch', function (event) {
    var requestURL = new URL(event.request.url);
    var freshResource = fetch(event.request).then(function (response) {
        var clonedResponse = response.clone();
        // Don't update the cache with error pages!
        if (response.ok) {
            // All good? Update the cache with the network response
            caches.open(CACHE_NAME).then(function (cache) {
                cache.put(event.request, clonedResponse);
            });
        }
        return response;
    });
    var cachedResource = caches.open(CACHE_NAME).then(function (cache) {
        return cache.match(event.request).then(function(response) {
            return response || freshResource;
        });
    }).catch(function (e) {
        return freshResource;
    });
    event.respondWith(cachedResource);
});

整个问题源于缓存中不存在该项目并且cache.match 返回错误的情况。在这种情况下,我需要做的就是获取实际的网络响应(通知return response || freshResource)

这个答案对我来说是Aha! 时刻(尽管实现方式不同): Use ServiceWorker cache only when offline

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-08
    • 1970-01-01
    • 1970-01-01
    • 2019-07-04
    • 1970-01-01
    • 1970-01-01
    • 2023-04-09
    • 1970-01-01
    相关资源
    最近更新 更多