flux in depth. store and network communication
DESCRIPTION
fluxTRANSCRIPT
-
7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog
http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 1/14
Flux in Depth. Store and NetworkCommunication.Edit
Thisisthesecond,andprobablybethelast,blogpostoftheseries"FluxinDepth".Inthefirstpostwedidaquickoverviewofflux,tookalookatthestateless,purecomponents,immutabledatastructuresandcomponentcommunication.Thistime,we'regoingtointroducethestoreandhowwecancommunicatewithservicesthroughthenetworkviaHTTP,WebSocketorWebRTC.Sincethefluxarchitecturedoesn'tdefineawayofcommunicationwithexternalservices,hereyoucanfindmywayofdealingwithnetworkcommunication.Ifyouhaveanysuggestionsoropinions,donothesitatetoleaveacomment.
StoreAswesaid,theUIinfluxisbuiltwithpurecomponents,whichare(mostly)notholdinganystate.However,ourapplicationcan'tbecompletelystateless.Wehaveatleastbusinessdata,UIstateandanapplicationconfiguration.Thestoreistheplace,whichkeepsthisdata.
Letspeekatthefluxdataflowonceagain:
Aswecanseefromthediagramabove,thedataflowstartsintheview,goestoanaction,whichinvokesthedispatcher,afterthatthestorecatchesdispatcher'seventandintheendthedataarrivesintheviewagain.Alright,sothestoreisresponsibleforprovidingthedatatotheview.Sofarsogood.Howwecanmakethestoredelivertherequiredbytheviewdata?Well,itcantriggeranevent!Recentlyobservablesaregettingquitepopular.Forgoodorbad,theyaregoingtobeincludedintheJavaScriptstandard.IfthismakesyouangrybecauseyouhavetolearnnewthingsandJavaScriptisgettingfatter,youcanfindtheguywhostaysbehindallofthishere:
MINKO GECHEV'S BLOG
menu
-
7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog
http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 2/14
Observablesaregoodwayofbuildingourstore.Iftheviewisabletoobservethestoreforchanges,itcanupdateitselfoncethestoreupdates.Letstakealookatthefollowingdesignpattern(yeah,myfriendsalreadynoticedI'mtalkingaboutdesignpatternsconstantlyanddidaninterventionformebutdidn'thelp).
Chain of Responsibility
Thisisadesignpattern,whichisexclusivelyusedintheeventdrivenprogramming.LetschangethecontextandtalkaboutDOMforawhile.Ibetyouknowthatyoucanlistenforanyeventonthedocument,forexampleonceauserclicksonabuttontheeventwillpropagatetotherootoftheDOMtree(eventually,ifnothingstopit)andbecaughtbyyourlistener:
document.addEventListener('click',e=>{alert(`Youactuallyclickedonelementwith#${e.target.getAttribute('id'alert(e.currentTarget===document)},false)
-
7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog
http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 3/14
Clickme
Clickme
RunwithJSAutorunJS
HTML CSS ES6/Babel Console Output HelpJSBin Save
Ifyouclickonthe awesomebutton ,you'llseetwoalertboxes:"Youactuallyclickedonelementwith#awesomebutton,notdirectlyondocument"and"true".Ifyouchangethethirdparameterof addEventListener to true ,theeventwillpropagateintheoppositedirection(i.e.fromtoptobottom,capturingmode).
WhyIsaidallofthis?Well,thisisthepatternChainofResponsibility:
Inobjectorienteddesign,thechainofresponsibilitypatternisadesignpatternconsistingofasourceofcommandobjectsandaseriesofprocessingobjects.Eachprocessingobjectcontainslogicthatdefinesthetypesofcommandobjectsthatitcanhandletherestarepassedtothenextprocessingobjectinthechain.Amechanismalsoexistsforaddingnewprocessingobjectstotheendofthischain.
Orifyou'rehavemoreenterprisetaste,hereistheUMLclassdiagramofthisdesignpattern:
Client Handler
+handle()
ConcreteHandlerA
+handle()
ConcreteHandlerB
+handle()
successor
WhydoweneedChainofResponsibility?Well,ourstoreisatreeofobjects,onceapropertyinaninternalnodeinthetreechanges,it'llpropagatethischangetotheroot.Therootcomponentintheviewwilllistenforeventstriggeredbythestoreobject.Onceitdetectsa
-
7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog
http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 4/14
changeit'llsetitsstate.I'msureitsoundsweirdandobfuscated,letstakealookatadiagram,whichillustratesasimplechatapplication:
From the Store to the View
Letstakealookatthefollowingdiagram,itillustratestheinitialsetupofourapplication:
Thetreeonthelefthandsideisthestore,whichserializedintoJSONlooksthefollowingway:
{"users":[{"name":"foo","id":1},{"name":"bar","id":2}],"messages":[{"text":"Heyfoo","by":2,"timestamp":1437147880686}]}
Thetreeontherighthandsideisthecomponenttree.Wealreadydescribedthecomponenttreesinthepreviouspart.Hereisasnippet,whichshowstherelationbetweenthe Chat storeandthe ChatBox component:
importReactfrom'react'importChatfrom'../store/Chat'
classChatBoxextendsReact.Component{constructor(props){super(props)Chat.on('change',c=>{this.setState(c)})}render(){
-
7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog
http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 5/14
return()}}
Basically,therootcomponent( ChatBox)issubscribedtothe change eventofthe Chat .Whenthe Chat emitsa change event,the ChatBox setsitsstatetobethecurrentstoreandpassesthestore'scontentdownthecomponenttree.That'sit.
Whathappensifsomethingchangeourstore?
Onthediagramabovesomethingchangedthefirstmessageinthe Chat store(letssaythetext propertywaschanged).Onceapropertyina message changes,themessageemitsaneventandpropagatesittotheparent(step 1)whichmeansthattheeventreachesthemessages collection.The messages collectiontriggerschangeeventandpropagatestheeventtothe chat (rootobject,step 2).The chat objectemitsachangeevent,whichisbeingcaughtbythe ChatBox component,whichsetsitsstatetothecontentofthestore.That'sit...
Inthenextsection,we'regoingtotakealookhowtheviewcanmodifythestoreusingActions.
From the View to the Store
Nowletssupposetheuserentersamessageandsendsit.Insideasendhandler,definedinMessageInput weinvoketheaction addMessage(text,user) the MessageActionsobject(step1)(peekatthefluxoverviewdiagramabove).The MessageActions explicitlyinvokesthe Dispatcher (step2),whichthrowsanevent.ThiseventisbeinghandledbytheMessages component(step3),whichaddsthemessagetothelistofmessagesandtriggersa
-
7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog
http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 6/14
change event.Nowwe'regoingtothepreviouscase"StoretoView".Allofthisisbetterillustratedonthefollowingdiagram:
Model vs UI state
Mostlikelyyou'rebuildinganapplication,whichworksonbusinessdataovergivendomain.Forexample,inourcasewehad:
MessagesUsers
However,inmostcases,thisisnotenough.YourapplicationalsohasaUIstate.Forexample,whethergivendialogisopenedorno,whatisthedialog'sposition,etc.Thedata,whichdefinesnowyourcomponentswillberendered,dependsonbothyourUIstateandthemodel.ThisisthereasonIcreateacombinedstore,whichpresentsboth.Forexample,ifweaddafewdialogstoourchatapplication,theJSONrepresentationofthestoremaylooklike:
{"users":[{"name":"foo","id":1},{"name":"bar","id":2}],"messages":[{"text":"Heyfoo","by":2,"timestamp":1437147880686}],"dialogsOpenStatus":{"nicknameInput":true,"editMessage":false}}
-
7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog
http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 7/14
IalwaysprefertohaveseparationbetweentheUIstateandthemodelbecausethecommunicationwithexternalservicesusuallyrequiresonlyhandlingchangesinthemodel,soeventsemittedbytheUIstoredoesnotconcernus.
Quick FAQ:
Alright,Igotit.SoifIhaveamousemoveevent,whichchangesthestorebyupdatingthemouseposition,weshouldgothroughtheentiredescribeddataflow?Thisdoesn'tseemlikequiteagoodidea.Ifyouhaveabigstoreandhugecomponenttree,rerenderingitonmousemovewillimpacttheperformanceofyourapplicationdramatically!Whatwillbethebiggestslowdown?Well,you'llhavetoserializethestoretoaPOJO(PlainOldJavaScriptObject),lateryouneedtopassittotherootcomponent,whichisresponsibleforpassingitdowntoitschildrenandsoon.Andallofthisbecauseoftwochangednumbers?Itiscompletelyunnecessary.InsuchcasesI'drecommendaddingeventlistenersinthespecificcomponent,whichdependsonthemousepositionandcreatingaseparatestoreforit.
Forexample,ifyou'reusing reactdnd inyourapplication,thedrag&dropcomponenthasitsownstate,whichdoesn'thavetobemergedwiththerestofthestore.Itcanliveindependently.LetmeshowyouwhatImeanonthefollowingdiagram:
Inthisexample,whenthestorecontainingthedialogpositionupdatesitdoesnotrequireupdateoftheentirecomponenttree.
HowshouldImakemystoretriggerevents?Thesamewayyoudidthatinthedispatcheruse EventEmitter .SincewewanttoimplementChainofResponsibility,youwillberequiredtokeepreferencetotheobject'sparentinordertopropagatetheevent.
-
7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog
http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 8/14
Remote ServicesThisisahottopic.Mostofthesinglepageapplicationsrequirecommunicationwithservicesthroughatransportprotocol,inordertofetchandstoredata.However,intheoverviewoffluxthere'snosuchthingas TransportChannel , RemoteService orwhatever.Ifthereareinvolvedalotofdifferentprotocols(forexampleI'mworkingonaapplication,whichcommunicateswithotherapplicationsandservicesthroughHTTP,WebSocketandWebRTCdatachannel)itcouldgetabithairyifyoudon'tcreatetheproperabstractions.
InthissectionI'lldescribethebasicsofthenetworkcommunicationandlaterwe'regoingtodiscussmoreinterestingdetails.
Alright,inthediagramwhichshowstheoverviewoffluxthereisa"hanging"action.There'snoincomingarrowtotheleftmostactionbutthere'soutgoingone:
From the Network to the UI
Wecanusethis"hanging"actioninordertointegratethecommunicationwiththeexternalservices.Letstakealookatthefollowingpicture,inordertovisualizebasiccommunicationwithexternalservice:
-
7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog
http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 9/14
Initwecantracehowanetworkeventisbeingprocessed.Thecloudisanexternalservice/application.Initiallywegetanewmessage,itisbeingprocessedbythe Serviceobject(itisblackonthediagrambecauseitislikeablackboxforusrightnow,itmaygetquitecomplexdependingonyourapplication),laterthesemanticsbehindthereceivedmessageisfoundandbasedonit, Service invokesa StoreAction .Nowtheflowgoesexactlythewaywedescribeditearlier(FromtheStoretotheView).We'regoodfornow.Butwhathappensifthestorechanges?Nothingsofar.
From the UI to the Network
Inordertosendnetworkeventsbasedonchangesofthestorewecanobserveitandperformaspecificactionbasedonthechange.Sinceitextends EventEmitter wecansimplyaddonchange handlerstothestoreinsidethe Service andthiswaywecaneasilyhandleallchangesandprocessthem:
-
7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog
http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 10/14
Butwhythe Service moduleshuldlistenforstorechanges?Can'titlistendirectlyonthedispatcher?Mostlikely,inthestorewe'llhavesomelogicforhandlingtheactionpassedbythedispatcher(forexampleformattherawdatapassedbytheview).Ifthe Service modulelistensforchangesatthedispatcherwewillduplicatethislogictwice.
Everythinglooksgoodsofar.Butthe Service moduleisstillahugeblackbox.InthenextsectionI'llsuggestasampledesignofthismodule.Ifyoudon'tagreewithsomething,haveanyquestionsorrecommendationsletmeknow.
The Service ModuleIwaswonderingwhethertouseUMLforshowingthecomponentsbuildingthe Servicemodule,howeverIchoosetomakeacolorfuldiagramliketheonebellow:
-
7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog
http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 11/14
Therearealotofboxeshere.Theyellowonesarepartofthefluxarchitecture.Theblueonesareresponsibleforsendingupdatesfromtheapplicationtotheremoteservice,theredonesareresponsibleforhandlingnetworkeventsandthegreenonesaretheintersectionbetweenthelasttwocategories.Onecomponentcouldbeimplementedwithafewclasses,we'renotrestrictingourselvestothesecomponents.Wecanthinkofthemmorelikecategoriesratherthenspecificclasses.Herewe'lldemonstrateasampledecompositionoftheservicemodule.Letsdescribethemostinterestingcomponentsonebyone.
Channel
Abstractchannel.Itcouldbeextendedby HTTPChannel , WebSocketChannel ,WebRTCDataChannel ,etc.
Package
The Package componentrepresentsthepackagesusedbyourprotocol.Therecouldbeahierarchyofpackagetypes.Forexample,ifwebuildourprotocolontopofJSONRPC,wemaywanttoextendthebase Package class.
Command
ImplementstheCommanddesignpattern.
CommandDispatcher
Responsiblefordispatchingcommands.There'sonemorelink,whichisnotrepresentedonthediagramthe CommandDispatcher ownsreferencetothe Channel component.Itcheckswhetherthechannelisopenbeforesendingthecommand,ifitisn'tthe CommandDispatcherretriesafteragiventimeout.Thiscomponentisalsoresponsibleforbufferingcommands,invokingtheirundoactionsincasethecommand'sexecutionfails.The CommandDispatchermayimplementdifferentdispatchingstrategies:
-
7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog
http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 12/14
Request/responseSlidingwindowtechniqueBuildagraphofthedependenciesbetweenthecommands,processatopologicalsortandinvokethecommandsintheappropriateorder
StoreObserver
The StoreObserver isresponsibleforhandlingchangeeventsofthestore.Onceitdetectschangeinthestoreitcreatesanewcommandusingthe CommandBuilder andinvokesitthroughthe CommandDispatcher .
NetworkObserver
Waitsfornewmessagesemittedbythedata Channel .Thiscomponentisresponsibleforparsingthemessagesandprocessingthem.Oncethemessageisparsed,basedonitscontentthe NetworkObserver invokesspecific Action .
Third-party ServicesIfyou'reusingathirdpartyservice(Twilioforexample)youcanprocessinasimilarfashion.Youcancreateawrapperoftheservice(inthecaseofTwilio,the Twilio global)andbringitinyourfluxdataflow.
Quick FAQ:
Isn't NetworkObserver a"Godclass"?Yep,itis.Youcandecomposeitintoafewsmallerclasses,samefor CommandDispatcherwhereyoucanusethestrategypatternfordispatchingthecommandsintheappropriateorder.
Whatarethese ProtocolDecorators?Sincewecancreateourprotocolbasedonanother,alreadyexistingprotocol(JSONRPC,BERTRPC,etc.),wecanprocesstheincomingmessagesbyusingachainofdecorators.Forexample,wereceiveabasicstring,nextthe JSONRPCDecorator canparseittoavalidJSONRPC messageandpassittothenextdecorator( YourCustomProtocolDecorator),etc.
Can'tIgetcascadingupdateswhenupdatethemodel?Can'tIreachaconditioninwhichtheviewupdatesthestore,itemitsachangeevent,whichisbeinghandledbythe Servicemodule,whichemitsanevent...etc.?Thiscanhappen.Therearetwosimplesolutions:emitchangeeventonlywhenthevalueofgivenpropertyisactuallybeingchangedemit uichange eventwhenupdatethemodelfromtheviewandemit serverchange eventwhenchangeitfromtheserver.Therootcomponentcanlistenfor /change/ events(yeah,thisisaregex)andtheservercanlistenfor uichange .
Ithrowaneventbutafewstoresarehandlingit?!
-
7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog
http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 13/14
Mostlikelyyouhavecollisionintheactiontypes.I'dsuggesttousethefollowingschemafornamingthem: storename:actionname orsomethingsimilar,whichguaranteesuniqness.
ConclusionThefirstpartofthispostshownhowwecanwirethestorewiththeview.Thesecondpartwasaboutthebasicideaofthenetworkcommunicationwithexternalservices.Thelastsectiondescribedasampleimplementationoftheblackboxresponsibleforhandlingexternalmessages,storechanges,serializationofthestoreandsendingitthroughthenetwork.Althoughthefirsttwopartswererelativelycanonicalandpredefinedbyflux,thelastchapterwascompletelycustomimplementation.WithitIwantedtoimplythatthemicroarchitectureweuse(MVC,MVP,MVVM,flux,whatever)doesnotprovideustheentireprojectdesign.Itonlyputssomerulesonhowweshouldorganizeourapplication,definesthemainbuildingblocksandhowwecanwirethemtogether,however,ifwewanttobuildareallifeapplication,mostlikelywe'llneedtoputsomeadditionaleffortthearchitectureortheframeworkwon'tbeabletosolveallourconcerns.
Minko GechevJavaScripthacker
FluxinDepth.StoreandNetworkCommunication.waspublishedonJuly18,2015.
-
7/19/2015 Flux in Depth. Store and Network Communication. Minko Gechev's blog
http://blog.mgechev.com/2015/07/18/flux-in-depth-store-network-communication-services/ 14/14
FluxinDepth.OverviewandComponents.4comments2monthsago
JavaScript,theweirdparts3commentsayearago
SingletoninJavaScript2commentsayearago
AngularJSinPatterns(Part3)1commentayearago
ALSOONMINKOGECHEV'SBLOG
0Comments MinkoGechev'sblog Login1Share SortbyBest
Startthediscussion
Bethefirsttocomment.
WHAT'STHIS?
Subscribe AddDisqustoyoursited Privacy
Recommend
(VIEW ALL POSTS)YOU MIGHT ALSO ENJOY
UsingJSXwithTypeScriptFluxinDepth.OverviewandComponents.EvenFasterAngularJSDataStructures
2015MinkoGechev.SofiaValley