最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to handle fetch events from the very beginning using a Service Worker? - Stack Overflow

programmeradmin2浏览0评论

I'm trying to build a basic service worker to handle all AJAX requests sent from my website.

Service worker is subscribed to the fetch event. I can handle all request sent but it doesn't work the first time the service worker is installed.

Once the service worker is installed, if I refresh the web page, then the fetch event handler works.

I want my service worker to fetch all requests from the very beginning. Is it possible?

Here's the code I have:

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('');
      })
      .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
  );
});

I'm trying to build a basic service worker to handle all AJAX requests sent from my website.

Service worker is subscribed to the fetch event. I can handle all request sent but it doesn't work the first time the service worker is installed.

Once the service worker is installed, if I refresh the web page, then the fetch event handler works.

I want my service worker to fetch all requests from the very beginning. Is it possible?

Here's the code I have:

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.');
      })
      .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
  );
});
Share Improve this question edited Dec 19, 2016 at 14:38 sdgluck 27.4k12 gold badges81 silver badges95 bronze badges asked Dec 19, 2016 at 14:20 noodle71noodle71 942 silver badges6 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 3

The default behaviour of is that a webpage must be refreshed before its service worker bees active. So, the "very beginning" for you (the user) is not the same "very beginning" of the service worker.

However, you can override this default behaviour by using clients.claim(). Read about it on MDN:

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

Note that for your use case you should ensure that the SW is registered and activated before firing any fetch events.

______

Read more about the service worker lifecycle in the "Service Worker Lifecycle" blog post. Here are some relevant bullet points...

  • A service worker won't receive events like fetch and push until it successfully finishes installing and bees "active".
  • By default, a page's fetches won't go through a service worker unless the page request itself went through a service worker. So you'll need to refresh the page to see the effects of the service worker. clients.claim() can override this default, and take control of non-controlled pages.

Yes, it is possible.

In order to catch the very beginning requests, Service Worker must take controls over the initial pages that call those requests right after it is being activated. And unfortunately, this is not enabled by default. You still have to call clients.claim for achieving this expected behaviour.

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

Thanks a lot for all the answers, finally this is the code.

I don't think it's the best solution but it works. Service worker handle all request from the very beginning even if you refresh the web page.

HTML:

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

  function init() {
    fetch('https://www.google.');
  }

  function subscribeToSWMessages() {
    navigator.serviceWorker.onmessage = function (event) {
      console.info("Broadcasted message received: %s", event.data.message);

      if (event.data.mand == "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({
          "mand": "swRegistrationOk",
          "message": "Service Worker registration ok"
        });
      })
      .catch(console.warn);
  }

</script>

</body>
</html>

Service worker:

// 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.mand == "swRegistrationOk") {
    event.waitUntil(sendActiveSignalToClients());
  }
});

function sendActiveSignalToClients() {

  self.clients.matchAll().then(function (clients) {
    clients.forEach(function (client) {
      client.postMessage({
        "mand": "swActive",
        "message": "Service Worker is active"
      });
    })
  })

}
发布评论

评论列表(0)

  1. 暂无评论