服务人员-具有动态参数的缓存页面

时间:2019-09-04 11:57:03

标签: asp.net-mvc service-worker workbox

我正在使用Service Worker(通过Workbox)来缓存.NET MVC索引视图的结果,该视图是一个简单的URL(例如https://mysite.local/MyWebsite/Product/Index)。请注意,缓存由页面本身以及在设计/编译时未知的网格中显示的数据(以JSON格式)提供的数据(即JSON数据是在运行时通过{{ 3}})。这一切都很好-脱机时进行缓存。

该网格为(单击时)转到另一MVC视图的每一行包含一个按钮。我还想缓存这些页面-说在我的初始网格中出现的前2个页面。因此,我不知道前两页的URL,因为它们包含从数据库中检索到的参数-它们的外观示例:-

https://mysite.local/MyWebsite/Product/LoadData

...'33'部分是从数据库中检索到的,因此无法提前知道

以下内容(在Service Worker中)对从初始索引页缓存的JSON数据进行迭代,获取每一行的ID字段并将其后缀添加到URL的末尾-然后,我尝试“提取”页面,然后将其缓存。

    cache.match('https://mysite.local/MyWebsite/Product/LoadData')
        .then(function(matchedResponse) {
            return matchedResponse.json();
        })
        .then(function (json) {
            for (var i = 0; i < json.data.length; i++) {
                const API_FurtherInformation_URL = 'https://mysite.local/MyWebsite/Product/FurtherInformation/' + json.data[i].Id + '/0';

                const apiLoadDataCallHandler = workbox.strategies.networkFirst({
                    cacheName: 'my-cache'
                });

                workbox.routing.registerRoute(
                    API_FurtherInformation_URL ,
                    apiLoadDataCallHandler 
                );

                self.addEventListener('install', event => {
                    event.waitUntil(
                      caches.open('my-cache')
                        .then(cache => cache.add(API_FurtherInformation_URL))
                    );
                });

                self.addEventListener('fetch', event => {
                    if (event.request.mode === 'navigate') {
                        event.respondWith(
                          fetch(event.request).catch(() => caches.match(API_FurtherInformation_URL))
                        );
                    }
                });
            }
        });
});

但是代码中的'install'和'fetch'事件逻辑都收到警告消息:-

“必须在辅助脚本的初始评估中添加'install'事件的事件处理程序”

“必须在辅助脚本的初始评估中添加'fetch'事件的事件处理程序”

...并且该页面未缓存

任何想法我能做什么-这种情况适合吗?

2 个答案:

答案 0 :(得分:1)

该错误消息表示: 在最初执行SW脚本之后,您不能添加self.addEventListener('fetch')self.addEventListener('install')-换句话说,您不能在循环中添加它们。您必须在首次执行时将这些事件侦听器添加到脚本的顶层。

您还应该注意,您添加的那些事件侦听器是事件的事件侦听器。它们不是像您所说的那样缓存某些内容的命令。

我认为您可以执行以下操作:

caches.open('my-cache')
  .then(cache => cache.add(API_FurtherInformation_URL))
在循环内部

(请注意,缓存可能已经打开,至少在外部作用域中具有该名称的变量)。您无需添加事件监听器!


总而言之,我认为您不应该真正实现这样的功能。它使您的Service Worker代码与API端点等非常耦合。我建议您重构代码,例如使其工作如下:

  1. 服务人员监听页面中的消息
  2. 邮件中包含应缓存的网址
  3. 收到消息后,SW会立即缓存网址
  4. 现在,当JS在页面上执行并为用户呈现url时,它可以向SW发送消息,并告诉它缓存所需的任何URL

页面和软件之间的消息传递应通过postMessage(https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage)来实现。

答案 1 :(得分:0)

我最后要做的是处理公共页面(共享的_Layout.cshtml)中的逻辑。无论用户最初如何访问网站,在需要时(通过提取)查询数据库(缓存刷新计时器)以及缓存动态页面,都将受到影响,因此当用户导航到我要缓存的页面时,它是新鲜的