Você está na página 1de 8

12/01/2017

ServiceWorker,MessageChannel,&postMessage

ServiceWorker, MessageChannel,
& postMessage
Last week I wrote an article about a caching strategy for progressive networking that uses
a cache rst and then goes to the networking, sharing messages between web pages and
a ServiceWorker to coordinate updates to cached content. Today Ill describe the inner
workings of the swivel library thats used to simplify message passing for
ServiceWorkers.

Nicols Bevacqua

Published a year ago | 10 minute read | 3

Asitturnsout,theresmanydifferentwaysinwhichyoucansharemessagesbetweena
ServiceWorker andthewebpagesitcontrols.

Aclientmaywanttomessagea ServiceWorker ,askingsomethingornotifyingabout


somethingthisisunicast(1to1)
A ServiceWorker maywanttosendareplytoaclientunicast
A ServiceWorker maywanttosendanupdatetoeveryclientunderitscontrola
broadcast(1tomany)message
A ServiceWorker maywanttosendanupdatetotheclientwherea fetch request
originatedunicast

Messaging the ServiceWorker

https://ponyfoo.com/articles/serviceworkermessagechannelpostmessage

1/8

12/01/2017

ServiceWorker,MessageChannel,&postMessage

Messaging the ServiceWorker

Inordertomessagea ServiceWorker ,youcanuseapieceofcodelikethefollowingsnippet.

worker.postMessage(data);

Bydefaultyouprobablywanttouse navigator.serviceWorker.controller ,theactive


ServiceWorkerinstanceforthecurrentpagethatcontrolsitsrequests,asthe worker .I
haventpersonallyfoundaneedyetfortalkingtoworkersotherthanthecontroller,whichiswhy
thatsthedefault worker youtalktoin swivel .Thatbeingsaid,thereareusecasesfor
them,whichiswhytheres swivel.at(worker) ,butletsgobacktoourfocusarea.

Theworkercansetupaneventhandlerthatdealswiththe data payloadwepostedfromthe


webpage.

self.addEventListener('message',functionhandler(event){
console.log(event.data);
});

Assoonasyouhavedifferenttypesofmessagesyouwanttosendtoworkers,thisbecomes
anissue.Youllhavetoturntoaconventionformessagerouting.Acommonconventionisto
defineanenvelopeforyourmessagesthathasa command propertyinit,sonowyoudsend
messageslikethefollowing.

worker.postMessage({command:'deleteCache',key:key});

Thentheworkerneedstobeupdatedwithacommandhandlingrouter,abunchof if willdo
inthesimplercase.Youcanseehowthecodestartsbecomingdilutedwithimplementation
details.
https://ponyfoo.com/articles/serviceworkermessagechannelpostmessage

2/8

12/01/2017

details.

ServiceWorker,MessageChannel,&postMessage

self.addEventListener('message',functionhandler(event){
if(event.data.command==='deleteCache'){
caches.delete(event.data.key);
}
});

Getting Replies from the ServiceWorker


Ifyouwanttheworkertobeabletoreplytothemessagethingsgetveryugly,veryquickly,
mostlybecausebrowsershaventimplementedthefinalAPIquiteyet.
Forthetimebeing,ontheclientsideyoullneedtosetupa MessageChannel ,bindalistener
to port1 andpassalong port2 whenpostingthemessage.

varmessageChannel=newMessageChannel();
messageChannel.port1.addEventListener('message',replyHandler);
worker.postMessage(data,[messageChannel.port2]);
functionreplyHandler(event){
console.log(event.data);//thiscomesfromtheServiceWorker
}

Onthe ServiceWorker side,itsnotthatfuneither.Youhavetoreference port2 ofthe


messageChannel using event.ports[0] ,asitstheportinpositionzeroofthe ports
passedalongwiththemessage.

self.addEventListener('message',functionhandler(event){

event.ports[0].postMessage(data);//handlethisusingthereplyHandlershowne
});

Browserswilleventuallyhavean event.source alternativeto event.ports[0] onthe


ServiceWorker sidethatdoesntneedustodoanyofthe
https://ponyfoo.com/articles/serviceworkermessagechannelpostmessage

MessageChannel stuffonthe

3/8

12/01/2017

ServiceWorker,MessageChannel,&postMessage

ServiceWorker sidethatdoesntneedustodoanyofthe MessageChannel stuffonthe


pages.Unfortunatelythatsnothereyet,andsowehavetoresortto MessageChannel for
now.

Broadcasting from a ServiceWorker to every client


Thisoneisstraightforward,butitsalsoprettydifferentfromthetwosituationswevejusttalked
about.And,quitehonestly,veryverbose.Ofcourse, ServiceWorker isallabout
expressivenessandbeingabletocaterformultipledifferentusecases,andweveallseenthe
veiledevilinseeminglysimplebutcleverlycomplicatedinterfacesliketheAppCachemanifest.

Thatbeingsaid,havingtotypethisoutsucks.Librarieswilldefinitelyhelpabstractthepain
away,while ServiceWorker cangoonbeingjustaboutthemostpowerfulfeaturethemodern
webhastooffer.

self.clients.matchAll().then(all=>all.map(client=>client.postMessage(data)));

Tolistentothesemessagesfroma ServiceWorker ,youcanregisteraneventlistenerlike


belowinyourwebpage.Notehowthelistenerisaddedon navigator.serviceWorker and
notonanspecific worker (like navigator.serviceWorker.controller ).

navigator.serviceWorker.addEventListener('message',functionhandler(event)
console.log(event.data);
});

Youprobablywanttokeepareferencetothe worker youreinterestedin,andthenfilteron


themessagelistenerby event.source .Thatwayyoullavoidmessagesbroadcastedfrom
workersotherthantheoneyoureexpectingmessagesfrom.
https://ponyfoo.com/articles/serviceworkermessagechannelpostmessage

4/8

12/01/2017

ServiceWorker,MessageChannel,&postMessage

workersotherthantheoneyoureexpectingmessagesfrom.

navigator.serviceWorker.addEventListener('message',functionhandler(event)
if(event.source!==worker){
return;
}
console.log(event.data);
});

Dual Channeling fetch Requests


Sendingupdatestotheoriginof fetch requestsis,perhaps,themostinterestingusecasefor
communicationbetween ServiceWorker andwebpages.Sendinganupdatetotheoriginof
a fetch requestiswhatmakesusingthecacheimmediatelyandthensendinganupdateas
soonaspossiblesoeffective.

self.on('fetch',functionhandler(event){
//replytoclienthere
});

Eventually, event willhavea clientId propertyidentifyingtheclientwheretherequest


camefrom.Wecouldthenusecodelikebelowtosendamessagetothe client using
client.postMessage .Nobrowserimplements event.clientId yet.

self.on('fetch',functionhandler(event){
event.respondWith(caches.match(event.request));
fetch(event.request).then(response=>response.json()).then(function(data)
self.clients.match(event.clientId).then(client=>client.postMessage(data));
});
});

https://ponyfoo.com/articles/serviceworkermessagechannelpostmessage

5/8

12/01/2017

ServiceWorker,MessageChannel,&postMessage

Youcouldstillusethebroadcastingmechanismdiscussedearlier,butitdgotoeveryclientand
notjusttheoriginofthe fetch event.Abetteralternative,fornow,maybetoissueanother
requestfromthepageafterload,maybeaddingacustomheaderindicatingthatweshould
forcea fetch onthe ServiceWorker side.

Swivel Makes Your Life Easier


Ifyoudprefertoavoidallofthisfrivolousknowledge,youmayliketo swivel likeRon
Swanson.

RonSwansonswivellingtoavoidhumancontact

Swivellinghasanumberofbenefits.TheAPIisunifiedunderaneventemitterstyle.Onthe
client,youcansendmessagestothe ServiceWorker likebelow.

swivel.emit('removecache','v1');

Thenontheworker,youcouldjustlistenforthatwithamatchingAPI.

swivel.on('removecache',(context,key)=>caches.delete(key));

Iftheworkerneedstoreply,itcanuse context.reply .
https://ponyfoo.com/articles/serviceworkermessagechannelpostmessage

6/8

12/01/2017

ServiceWorker,MessageChannel,&postMessage

Iftheworkerneedstoreply,itcanuse context.reply .

swivel.on('removecache',functionhandler(context,key){
caches.delete(key).then(function(){
context.reply('removedcache','ok','whatever');
});
});

Theclientthatsentthemessagethengetstohandlethereplyaslongastheyrelisteningfor
the removedcache event.NotehowtheAPIhereisidenticaltotheAPIforlisteningon
eventsontheServiceWorker.

swivel.on('removedcache',functionhandler(context,success,metadata){
//dosomethingelse
});

When ServiceWorker hasimportantannouncements,itcanbroadcasttoeveryclient.

swivel.broadcast('announcement',{super:'!important'});

Broadcastedmessagescanbelistenedusingtheexactsame swivel.on APIintheclient


side.Inadditionto swivel.on ,theresalso swivel.once thatbindsonetimeevent
handlers,and swivel.off toremoveeventhandlers.

Lastly,aswementionedearlieryoucaninteractwithdifferentServiceWorkerinstances.Instead
ofusingthe swivel.* APIdirectly,youcoulduse swivel.at(worker).* instead.
Messagessentfromaclientusing swivel.at(worker).emit willonlygoto worker ,and
messagesbroadcastedby worker willonlybeavailabletolistenersregisteredusing

swivel.at(worker).on .Thiskindofscopinghelpspreventaccidentswhenphasingoutold
workersandwheninstallingnewones.
https://ponyfoo.com/articles/serviceworkermessagechannelpostmessage

7/8

12/01/2017

ServiceWorker,MessageChannel,&postMessage

YoucancheckoutthefulldocumentationonGitHub.

ServiceWorker , MessageChannel ,& postMessage .Oh,my!

https://ponyfoo.com/articles/serviceworkermessagechannelpostmessage

8/8

Você também pode gostar