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

javascript - Refresh page on controllerchange in service worker - Stack Overflow

programmeradmin11浏览0评论

I have a simple service worker with button update when new service worker is in queue. After update I want to make page refresh on controllerchange but nothing happens. All in all service worker is updated live but following that course () they try to add that refresh for some reason.

In js:

const updateButton = document.querySelector('.js-update-btn')

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('sw.js')
  .then(function (reg) {
    if (!navigator.serviceWorker.controller) {
      return
    }

    if (reg.waiting) {
      updateReady(reg.waiting)
      return
    }

    if (reg.installing) {
      trackInstalling(reg.installing)
      return
    }

    reg.addEventListener('updatefound', function () {
      trackInstalling(reg.installing)
    })
  })

  var refreshing
  navigator.serviceWorker.addEventListener('controllerchange', function () {
    if (refreshing) return
    window.location.reload()
    refreshing = true
  })
}

function updateReady (worker) {
  updateButton.disabled = false

  updateButton.addEventListener('click', function () {
    updateButton.disabled = true
    worker.postMessage({action: 'skipWaiting'})
  })
}

function trackInstalling (worker) {
  worker.addEventListener('statechange', function () {
    if (worker.state == 'installed') {
      updateReady(worker)
    }
  })
}

In sw.js:

self.addEventListener('message', function (event) {
  if (event.data.action == 'skipWaiting') {
    self.skipWaiting()
  }
})

I have a simple service worker with button update when new service worker is in queue. After update I want to make page refresh on controllerchange but nothing happens. All in all service worker is updated live but following that course (https://www.udacity.com/course/offline-web-applications--ud899) they try to add that refresh for some reason.

In js:

const updateButton = document.querySelector('.js-update-btn')

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('sw.js')
  .then(function (reg) {
    if (!navigator.serviceWorker.controller) {
      return
    }

    if (reg.waiting) {
      updateReady(reg.waiting)
      return
    }

    if (reg.installing) {
      trackInstalling(reg.installing)
      return
    }

    reg.addEventListener('updatefound', function () {
      trackInstalling(reg.installing)
    })
  })

  var refreshing
  navigator.serviceWorker.addEventListener('controllerchange', function () {
    if (refreshing) return
    window.location.reload()
    refreshing = true
  })
}

function updateReady (worker) {
  updateButton.disabled = false

  updateButton.addEventListener('click', function () {
    updateButton.disabled = true
    worker.postMessage({action: 'skipWaiting'})
  })
}

function trackInstalling (worker) {
  worker.addEventListener('statechange', function () {
    if (worker.state == 'installed') {
      updateReady(worker)
    }
  })
}

In sw.js:

self.addEventListener('message', function (event) {
  if (event.data.action == 'skipWaiting') {
    self.skipWaiting()
  }
})
Share Improve this question edited Jan 27, 2017 at 14:39 Jeff Posnick 56.1k14 gold badges147 silver badges174 bronze badges asked Jan 27, 2017 at 9:48 KrystusKrystus 3153 gold badges4 silver badges14 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 11

I would recommend following the example from the sw-precache demo code.

Here's a very concise, modified version of that example that will force a page reload when there's an update to an already installed service worker. (I'd argue that it might be more user-friendly to display a message on the page asking the user to reload manually, though, so that you don't end up interrupting whatever they were doing on the page.)

navigator.serviceWorker.register('/service-worker.js').then(reg => {
  reg.onupdatefound = () => {
    const installingWorker = reg.installing;
    installingWorker.onstatechange = () => {
      if (installingWorker.state === 'installed' &&
          navigator.serviceWorker.controller) {
        // Preferably, display a message asking the user to reload...
        location.reload();
      }
    };
  };
});

After many attempts I come with something like that.

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('sw.js')
  .then(function (reg) {
    if (!navigator.serviceWorker.controller) {
      return
    }

    reg.addEventListener('updatefound', function () {
      const newWorker = reg.installing
      newWorker.state

      var refreshing

      newWorker.addEventListener('statechange', () => {
        if (newWorker.state == 'activated') {
          if (refreshing) return
          window.location.reload()
          refreshing = true
        }
      })

      trackInstalling(reg.installing)
    })
  })
}

It's working. Is there any flaws of that code?

发布评论

评论列表(0)

  1. 暂无评论