Exploring Service Workers

Message Handling in the Service Worker

Kyle Simpson

Kyle Simpson

You Don't Know JS
Exploring Service Workers

Check out a free preview of the full Exploring Service Workers course

The "Message Handling in the Service Worker" Lesson is part of the full, Exploring Service Workers course featured in this preview video. Here's what you'd learn in this lesson:

Kyle hooks up the other end of communication between the service worker and the client. The client and service worker are then able to communicate about logged in and online status.


Transcript from the "Message Handling in the Service Worker" Lesson

>> Kyle Simpson: All right, so now we're in our Service Worker, and we need to hook up the other end of that communication. The blog that's gonna be sending status updates, but we're also gonna wanna be requesting them. Since we're making a pretty major change to our Service Worker, I'm gonna go ahead and bump the version, and then we're going to,

>> Kyle Simpson: Set up some other variables like isOnline.
>> Kyle Simpson: We'll assume true for that one. And then isLoggedIn, we'll assume false for that one.
>> Kyle Simpson: And then we want to set up some event listeners,
>> Kyle Simpson: Actually, just one. We're gonna listen for the message event.
>> Kyle Simpson: So the one place that we want to ask for an update, we may receive updates at other times.

But the one time we definitely wanna ask for an update is right here. So I'm gonna take out this console log message since it seems a bit redundant at this point. I'm gonna just say await sendMessage, which we're gonna define. And you remember from the blog that the thing that we're expecting to see is called requestStatusUpdate.

So let's actually pass in requestStatusUpdate.
>> Kyle Simpson: All right, let's define our sendMessage. We'll make it an async function sendMessage.
>> Kyle Simpson: Now, this one is a little bit more complex since, again, as I mentioned, we have multiple clients that we might be talking to. So we need to first get a list of all those clients.

>> Kyle Simpson: You remember when I was talking about clients.claim? Here we're gonna do another call on that client API, it's called clients.matchAll. And we're gonna configure that matchAll call to include uncontrolled clients.
>> Kyle Simpson: A little long line length there. Okay, so now we want to send something to all of them.

So I'm going to do a Promise.all, because I'm gonna turn that list of clients into a list of promises. These post messages in Service Workers are promise returning APIs because they're synchronous. So we need to listen for all those promises to finish so that we know that we're done.

So I'm gonna take allClients and I'm gonna map it,
>> Kyle Simpson: With,
>> Kyle Simpson: Send the client message.
>> Kyle Simpson: Promise.all, don't forget, takes an array. So I forgot to put that, you gotta put the array in there.
>> Kyle Simpson: All right, we're gonna make a message channel. Remember I referred to that this is a special kind of way of creating multiple things.

Because we just have the one Service Worker that lots of people are talking to, and we need to manage who we're getting responses from. We're gonna make a new message channel for each client that we're talking to. So I'll say, = new MessageChannel.
>> Kyle Simpson: And I'm gonna listen for messages from that MessageChannel, and route them to my single onMessage handler.

>> Kyle Simpson: Sorry, I can't listen directly on the channel, I have to listen on the port that is created. So remember, it creates two ports, one for me and one for the remote. So I'm gonna say, chan.port1.onMessage, and then I'm gonna say client.postMessage,
>> Kyle Simpson: I'm gonna send the message.

>> Kyle Simpson: And the place that I'm gonna send it to specifically is channel.port2.
>> Kyle Simpson: So in other words, port1 is me, that's how I receive messages, port2 is how you receive messages. And I'm gonna send two port2 and listen on port1.
>> Kyle Simpson: I'm gonna return this because client.postMessage returns us a promise.

So we'll listen for that promise, that flows into the array, which flows into Promise.all.
>> Kyle Simpson: I just realized I don't need those square brackets after all, because that's what .map is doing. That would have created a problem. So this should be Promise.all with parentheses, not square brackets.
>> Kyle Simpson: So let's review where we're at in our main.

In other words, whenever we start up, we're gonna call sendMessage. We're gonna request a status update, that status update's gonna come from our various clients. Be aware that we're creating a single state store of these two variables. And we are asking potentially multiple clients to update that. If those clients were in different states for some reason, we would want to be doing more than just updating a single set of boolean variables.

We'd wanna have some list of all the different state sets that we're paying attention to, and store the data in each one of those. For our purposes, the state's simple enough that I can't imagine a scenario where you're gonna be online in one and not online in the other, or something like that.

But do be aware, if you're gonna be keeping stuff in sync like this, if you have multiple clients open, like the user's opened up multiple tabs, you might be getting different information. Which would manifest itself in a race condition in your app, so be careful with that.
>> Kyle Simpson: Last thing we wanna do here is write our onMessage function.

>> Kyle Simpson: It's going to receive,
>> Kyle Simpson: Our onMessage function is going to receive an event object which we will just destructure into the data. And we want to check to see if this is a message that's given us a status update. So if,
>> Kyle Simpson: I guess we can say If{data.statusUpdate}.

>> Kyle Simpson: So we wanna update our two variables, and I'm gonna use destructuring to save time there. So I'm gonna say that (isOnline, isLoggedIn) = data.statusUpdate.
>> Kyle Simpson: I'm destructuring that object and assigning it to the variables of those same property names.
>> Kyle Simpson: For good measure, let's go ahead and do a console log statement, so that we can see our Service Worker changing its state.

So Service Worker, let's do v, version,
>> Kyle Simpson: isOnline,
>> Kyle Simpson: isLoggedIn.
>> Kyle Simpson: That way, we can just verify that it is in fact getting the status updates that we want.
>> Kyle Simpson: Okay, I think we've made all the changes we need both on the blog side and the Service Worker side, so let's go test it out.

Now before you do any kind of refreshing, let's come over to our developer tools. Let's check on the status of things. You notice that this says, in my browser, it's 368 cuz I've had 367 previous mistakes with my Service Worker, or previous versions of my service worker, I guess, so mine says 368.

We're just gonna wanna make sure that, when we refresh, that that changes, and it should, but we just wanna make sure that it changes. So I'm going to do a simple refresh of the page, or I could do a navigation, I guess you can just click a navigation.

And if we come over here, you'll notice now it has moved to 369. Let's look at our console, and I'll just temporarily zoom this so you can read. We see that Service Worker 2 is installed, version 2. statusUpdate true, isOnline true, but not logged in.
>> Kyle Simpson: If I clear this console and then, in my network, I'm gonna have to zoom out here, I toggle offline, and we go back to our console.

You notice that the Service Worker has now been notified that we are offline. Still not logged in, but now we are offline. When we come back online,
>> Kyle Simpson: Now our Service Worker knows that we're back online.
>> Kyle Simpson: Let's check the isLoggedIn part, if I actually go log in,

>> Kyle Simpson: I'm not yet logged in, which is why it says false, I'll clear that,
>> Kyle Simpson: But once I log in,
>> Kyle Simpson: Now it says isLoggedIn true. So our Service Worker's being notified of our various state changes, our online and our logged in status. If we log back out, now the Service Worker knows that we're logged out.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now