【问题标题】:How to handle fetch events from the very beginning using a Service Worker?如何使用 Service Worker 从一开始就处理 fetch 事件?
【发布时间】:2016-12-20 01:05:06
【问题描述】:

我正在尝试构建一个基本的服务工作者来处理从我的网站发送的所有 AJAX 请求。

Service Worker 订阅了 fetch 事件。我可以处理所有发送的请求,但在第一次安装 service worker 时它不起作用。

一旦安装了 service worker,如果我刷新网页,那么 fetch 事件处理程序就会工作。

我希望我的服务人员从一开始就获取所有请求。有可能吗?

这是我的代码:

index.html

<!DOCTYPE html>
<html>
<body>
<h2>Service Worker Demo Page</h2>
<script type="text/javascript">

  if (navigator.serviceWorker) {

    navigator.serviceWorker.register('./sw.js')
      .then(function (registration) {
        console.debug('Registration within scope %s. More details %O', registration.scope, registration);
        return fetch('https://www.google.com');
      })
      .then(console.info)
      .catch(console.warn);

  }

</script>

</body>

sw.js

self.addEventListener('fetch', function (e) {
  console.info('%s request to %s. More details: %o'
    , e.request.method
    , e.request.url
    , e
  );
});

【问题讨论】:

    标签: javascript service-worker


    【解决方案1】:

    的默认行为是必须在其 service worker 激活之前刷新网页。因此,您(用户)的“最开始”与 Service Worker 的“最开始”不同。

    但是,您可以使用clients.claim() 覆盖此默认行为。阅读它on MDN

    // sw.js
    self.addEventListener('activate', function(event) {
      event.waitUntil(self.clients.claim());
    });
    

    请注意,对于您的用例,您应确保在触发任何 fetch 事件之前注册并激活 SW。

    ______

    "Service Worker Lifecycle" 博客文章中了解有关服务工作者生命周期的更多信息。以下是一些相关的要点...

    • 在成功完成安装并变为“活动”之前,Service Worker 不会收到诸如 fetch 和 push 之类的事件。
    • 默认情况下,除非页面请求本身通过服务工作者,否则页面的提取不会通过服务工作者。所以你需要刷新页面才能看到 service worker 的效果。 clients.claim() 可以覆盖此默认值,并控制非受控页面。

    【讨论】:

      【解决方案2】:

      是的,有可能。

      为了捕获最开始的请求,Service Worker 必须在激活后立即控制调用这些请求的初始页面。不幸的是,默认情况下未启用此功能。您仍然需要致电 clients.claim 才能实现此预期行为。

      self.onactivate = function(event){
        event.waitUntil(self.clients.claim());
      };
      

      【讨论】:

        【解决方案3】:

        非常感谢大家的回答,最后就是代码了。

        我认为这不是最好的解决方案,但它确实有效。即使您刷新网页,Service Worker 也会从一开始就处理所有请求。

        HTML:

        <!--index.html-->
        <!DOCTYPE html>
        <html>
        <body>
        <h2>Service Worker Demo Page</h2>
        <script type="text/javascript">
        
          function init() {
            fetch('https://www.google.com');
          }
        
          function subscribeToSWMessages() {
            navigator.serviceWorker.onmessage = function (event) {
              console.info("Broadcasted message received: %s", event.data.message);
        
              if (event.data.command == "swActive") {
                init();
              }
            };
          }
        
          if (navigator.serviceWorker) {
        
            subscribeToSWMessages();
        
            navigator.serviceWorker.register('./sw.js')
              .then(function (registration) {
                console.debug('Registration within scope %s. More details %O', registration.scope, registration);
                navigator.serviceWorker.controller.postMessage({
                  "command": "swRegistrationOk",
                  "message": "Service Worker registration ok"
                });
              })
              .catch(console.warn);
          }
        
        </script>
        
        </body>
        </html>
        

        服务工作者:

        // index.js
        self.addEventListener('activate', function (event) {
          event.waitUntil(self.clients.claim().then(sendActiveSignalToClients));
        });
        
        self.addEventListener('fetch', function (e) {
          console.info('%s request to %s. More details: %o'
            , e.request.method
            , e.request.url
            , e
          );
        });
        
        self.addEventListener('message', function (event) {
          console.info("Broadcasted message received: %s", event.data.message);
        
          if (event.data.command == "swRegistrationOk") {
            event.waitUntil(sendActiveSignalToClients());
          }
        });
        
        function sendActiveSignalToClients() {
        
          self.clients.matchAll().then(function (clients) {
            clients.forEach(function (client) {
              client.postMessage({
                "command": "swActive",
                "message": "Service Worker is active"
              });
            })
          })
        
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2018-07-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-03-12
          • 2020-11-04
          相关资源
          最近更新 更多