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

An example using Service Worker? #27

Closed
alastaircoote opened this issue Oct 17, 2017 · 10 comments
Closed

An example using Service Worker? #27

alastaircoote opened this issue Oct 17, 2017 · 10 comments
Assignees

Comments

@alastaircoote
Copy link

When I saw this I assumed I could slot a service worker in the same place a web worker was being used in the example, but service workers don't have self.postMessage, so it doesn't work. I've got it working now by hooking up the proxy through a MessagePort in a message event - is that the best way to do it?

Either way, it would be great to have an example showing the best practise for this.

@surma
Copy link
Collaborator

surma commented Oct 17, 2017

You are right, a ServiceWorker doesn’t have self.postMessage at there might be potentially multiple open windows. So yeah, sending a MessagePort is one good solution. Another option would be to get the actual window object using self.clients.get() or self.clients.matchAll().

It’s probably a good idea for me to write an example for this.

Hope this helps.

@surma surma closed this as completed Oct 17, 2017
@surma
Copy link
Collaborator

surma commented Oct 17, 2017

I am curious, tho. What is your current use-case with Comlink + ServiceWorker? What are you exposing?

@alastaircoote
Copy link
Author

I'm using Notification APIs that are only available in a SW (as far as I know), as well as checking progress of caching events. I know it's not a core use of Comlink but I've found it useful so far!

@surma
Copy link
Collaborator

surma commented Oct 17, 2017

You can use Notification API without SW :)

Progress of caching is definitely an interesting use case.

@alastaircoote
Copy link
Author

AFAIK you can show a notification, but can't for example call getNotifications():

https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/getNotifications

Would love to be wrong though :)

@surma
Copy link
Collaborator

surma commented Oct 17, 2017

That’s correct. I thought you just wanted to show notifications

@gruns
Copy link
Contributor

gruns commented Nov 2, 2017

+1 for a canonical, best-practice example of establishing an RPC connection with a ServiceWorker.

@surma surma reopened this Jun 15, 2018
@surma surma self-assigned this Jun 15, 2018
@jeffposnick
Copy link

I'm trying to follow the recommendation in #27 (comment):

Another option would be to get the actual window object using self.clients.get() or self.clients.matchAll().

While the WindowClient interface has a postMessage() method, it doesn't have addEventListener() or removeEventListener(), so trying to do something like:

class RunInSW {
  // ...
}

self.addEventListener('message', async (event) => {
  if (event.data === 'init-comlink') {
    const clients = await self.clients.matchAll();
    for (const client of clients) {
      Comlink.expose(RunInSW, client);
    }
  }
});

leads to

Error: endpoint does not have all of addEventListener, removeEventListener and postMessage defined

@jeffposnick
Copy link

jeffposnick commented Jun 15, 2018

Here's what I've come up with so far, which seems to work:

In the window context:

function initComlink() {
  const channel = new MessageChannel();
  navigator.serviceWorker.controller.postMessage(channel.port2, [channel.port2]);
  window._runInSW = Comlink.proxy(channel.port1);
  channel.port1.start();
}

if (navigator.serviceWorker.controller) {
  initComlink();
}
navigator.serviceWorker.addEventListener('controllerchange', initComlink);

In the SW context:

self.addEventListener('message', (event) => {
  if (event.data instanceof MessagePort) {
    Comlink.expose(api, event.data);
    event.data.start();
  }
});

@surma
Copy link
Collaborator

surma commented Jun 15, 2018

I think I like your solution better. I’ll adjust my PR :)

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

No branches or pull requests

4 participants