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

It's a pain to get a handle to the page's SW now that we've moved to events. #174

Closed
slightlyoff opened this issue Feb 7, 2014 · 13 comments

Comments

@slightlyoff
Copy link
Contributor

It's sort of a pain in the butt to gate an operation on the availability of an SW now that we've removed ::ready(). E.g.:

function ready() {
  var sw = navigator.serviceWorker;
  return new Promise(function(resolve, reject) {
    if (!sw.active) {
      sw.register("/service_worker.js", { scope: "*" }).then(resolve, reject);
    } else {
      resolve(sw.active);
    }
  });
}

ready().then(...);

It's simpler to always register, of course, but it feels wrong somehow. Do I just need to get over this?:

function ready() {
  return sw.register("/service_worker.js", { scope: "*" });
}

ready().then(...);
@jakearchibald
Copy link
Contributor

Without always-register, this…

sw.register('...', {scope: '...'});

…becomes…

var sw = navigator.serviceWorker;
var workerUrl = '...';
var workerScope = '...';

if (!sw.active || sw.active.url == workerUrl && sw.active.scope == workerScope) {
  sw.register(workerUrl, {scope: scope});
}

@alecf
Copy link
Contributor

alecf commented Feb 7, 2014

+1 to bringing back register()

remember that we changed the register() promise to return the moment the script has been parsed and eval'ed.. so the final availability is gated on oninstall, which is only going to fire if the sw is being installed, so you have to do even more acrobatics to only listen for oninstall when there's no active SW, etc...

@slightlyoff
Copy link
Contributor Author

bringing back register()? or ready()?

@alecf
Copy link
Contributor

alecf commented Feb 7, 2014

sorry I meant ready()

@jungkees
Copy link
Collaborator

Can anyone drop a snippet that resolves the above mentioned problem using the revived ready() method? Is it something like this?

var sw = navigator.serviceWorker;

sw.ready().then(function(sw) {
  // in this case, the scriptURL and the scope are not passed. 
  // if (!sw.active): how's the platform supposed to deal with the internal registration?
});

@annevk
Copy link
Member

annevk commented Feb 13, 2014

I don't understand ready(). How is it different from register()?

@alecf
Copy link
Contributor

alecf commented Feb 13, 2014

We're going to have to spec ready() a little more specifically - I was roughly interpreting it as "as soon as everything settles" meaning that any in-process registration is complete. But that leaves a lot of room for interpretation.

I guess I'd imagine developers want to put some boilerplate on the top of all their pages to the effect of:

navigator.serviceWorker.register("foo.js").then(function(sw) {
    return sw.ready().then(function(sw) {
        // here we're guaranteed to have the above registration complete, whether it was
        // already registered or not
    });
});

I think another related thing that we've inadvertently decided is that the upgrade case is more or less a completely background situation.. meaning that if foo.js has updated since the last pageload (meaning there already is a registration for foo.js, but it has gone stale since the last pageload) then the above flow would still resolve immediately with the existing stale registration, and upgrading would happen in the background. This is probably part of a larger discussion though, as I don't think we've formalized that.

@alecf
Copy link
Contributor

alecf commented Feb 13, 2014

@annevk I think given that last paragraph of mine, ready() and register() are very similar, except that register() means "also register a script if it hasn't already been registered"

@annevk
Copy link
Member

annevk commented Feb 14, 2014

Yeah, we agreed that updates would happen in the background and that only if register specified a different URL or scope things would happen. Given that I don't really see how you could avoid having to write register() and use ready() instead.

@jakearchibald
Copy link
Contributor

if (navigator.serviceWorker.active) {
  // this page has a worker
}

navigator.serviceWorker.addEventListener('activate', function() {
  // navigator.serviceWorker.active has changed
  // which can only happen if it calls .replace() in oninstall
});

navigator.serviceWorker.register("foo.js").then(function(sw) {
  if (sw == navigator.serviceWorker.active) {
    // registration was most likely a no-op
  }
  else {
    // sw is an installing/installed worker
  }

  sw.ready().then(function() {
    // what does this mean?
  });
});

If you want to show installation happening, you'd listen for the install, installend etc etc events on navigator.serviceWorker. The install event would give you the serviceworker object in case you wanted to listen for postmessage stuff.

You'd use the promise returned by navigator.serviceWorker.register to catch failures. If you had a "click here to install the serviceworker" button you may use it to start/stop a spinner.

If you want to react to a change in navigator.serviceWorker.active, the activate event on navigator.serviceWorker gives you this. This means you get to hear about changes to navigator.serviceWorker.active that began with a registration call from another tab (or an automatic update). Also, navigator.serviceWorker.active can change multiple times throughout the life of the page, so an event makes more sense.

I guess I'm asking, what does sw.ready() do? What does ready mean in this context?

To answer the title of the ticket, navigator.serviceWorker.active gives you access to the page's SW. And navigator.serviceWorker.onactivate tells you when that changes, which may have nothing to do with a registration from the page.

@KenjiBaheux
Copy link
Collaborator

A few things have changed since then. Is this issue still valid?

@jungkees
Copy link
Collaborator

jungkees commented Aug 5, 2014

Now we have navigator.serviceWorker.ready and navigator.serviceWorker.controller.

@jungkees jungkees closed this as completed Aug 5, 2014
@jakearchibald
Copy link
Contributor

Hah, went to close this, but was beaten to it by hours. Should have refreshed.

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

6 participants