Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

registration.ready promise #770

Open
jakearchibald opened this issue Oct 28, 2015 · 2 comments
Open

registration.ready promise #770

jakearchibald opened this issue Oct 28, 2015 · 2 comments

Comments

@jakearchibald
Copy link
Contributor

To wait for the current registration to get an active worker. This helps explain navigator.serviceWorker.ready

@jakearchibald
Copy link
Contributor Author

Here's a rough polyfill for those looking for one:

function regReady(reg) {
  return new Promise((resolve, reject) => {
    if (reg.active) {
      resolve();
      return;
    }

    if (!reg.installing && !reg.waiting) {
      reject(Error('Install failed'));
      return;
    }

    (reg.installing || reg.waiting).addEventListener('statechange', function() {
      if (this.state == 'redundant') {
        reject(Error('Install failed'));
      } else if (this.state == 'activated') {
        resolve();
      }
    });
  });
}

@ithinkihaveacat
Copy link
Contributor

ithinkihaveacat commented Oct 6, 2016

It would be also useful if there were a way to wait for a specific worker to become active and controlling the page. (If, for example, you have versioned your service worker (and JS, CSS, etc.) and your HTML depends on a particular version.)

I think the following accomplishes this, though I keep finding edge cases I've missed:

function registerReady(script, options) {
  return navigator.serviceWorker.register(script, options).then(r => {
    const incoming = r.installing || r.waiting;
    if (r.active && !incoming) {
      return r;
    }
    return new Promise(resolve => {
      const l = e => {
        if (e.target.state === 'activated' || e.target.state === 'redundant') {
          incoming.removeEventListener('statechange', l);
          if (e.target === navigator.serviceWorker.controller) {
            resolve(r);
          }
        }
      };
      incoming.addEventListener('statechange', l);
    });
  });
}

It can be used as a direct replacement for navigator.serviceWorker.register():

// Fulfilled when '/sw.06fdc991c6a4.js' is active *and* controlling the page (maybe never)
const reg1 = registerReady('/sw.06fdc991c6a4.js', options);

To contrast with some other options:

// Fulfilled when browser "starts executing" '/sw.06fdc991c6a4.js'
const reg2 = navigator.serviceWorker.register('/sw.06fdc991c6a4.js', options);

// Fulfilled when (some) service worker is active (may not be controlling the page)
const reg3 = navigator.serviceWorker.ready;

// Fulfilled when '/sw.06fdc991c6a4.js' is active (may not be controlling the page)
const reg4 = regReady(reg2); // as above

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants