This post continues to answer "what is SmartJs". In this article we look at the R and the T. How does SmartJs implement Real Time communications? Read on to find out...
Network Events are Events too
In SmartJs a number of network communication channels are available:
All of them use the same Publish/Subscribe model to loosely couple the interactions. In fact in SmartJs I go so far as to call it a Virtual Pubsub because an event could be Published on one device and consumed by other devices.
Underneath, there are two modules that are handling the communication infrastructure. One is the proxy for Server on the client-side and the other is the proxy for Client on the server-side. SmartJs was designed to allow these two modules to be able to swap out with other real time library implementations, or even plain Ajax.
- Client->Server
- Client->Client
- Server->Client
- Client->Group
- Server->Group
All of them use the same Publish/Subscribe model to loosely couple the interactions. In fact in SmartJs I go so far as to call it a Virtual Pubsub because an event could be Published on one device and consumed by other devices.
Underneath, there are two modules that are handling the communication infrastructure. One is the proxy for Server on the client-side and the other is the proxy for Client on the server-side. SmartJs was designed to allow these two modules to be able to swap out with other real time library implementations, or even plain Ajax.
Implementing Open-Closed Principle in the SmartJs client-server Interface
In the SmartJs client's proxy module for the Server we have the implementation of the function:
This is where information is received from the server, and it is wired directly up to a Publish.
In this same module we find that the client calls the server using this function:
It provides a callback which runs when the event is processed. It is never the responsibility of the callback to handle any resultant data. It is only there to provide success or failure feedback in the case where that is possible. For example, when attempting to create a new Topic, it will return a failure in case that Topic name is taken. But if the Topic name is not taken, a separate message will come back Published containing the new Topic's data. This is an example of SRP applied to a functional interface.
Similarly the server implements:
This is where the information sent by the client arrives to the server. There it is separated into data or group handling and further separated within the data or group handlers.
The server makes calls to connected clients using the function:
It is the data structures passed through these functions that determines the routing and handling. The functions themselves are open to extension while remaining closed to modification.
The dataContext and groupContext modules provide segregated interfaces to the server functionality. These populate the traffic "kind" attribute with "data" and "group", respectively. Conceivably, other new modules could be developed that make use of the server proxy conduit, without ever needing to change the server module. This is a great example of OCP.
- nowjs.eventServerToClient
This is where information is received from the server, and it is wired directly up to a Publish.
In this same module we find that the client calls the server using this function:
- nowjs.eventClientToServer
It provides a callback which runs when the event is processed. It is never the responsibility of the callback to handle any resultant data. It is only there to provide success or failure feedback in the case where that is possible. For example, when attempting to create a new Topic, it will return a failure in case that Topic name is taken. But if the Topic name is not taken, a separate message will come back Published containing the new Topic's data. This is an example of SRP applied to a functional interface.
Similarly the server implements:
- nowjs.eventClientToServer
This is where the information sent by the client arrives to the server. There it is separated into data or group handling and further separated within the data or group handlers.
The server makes calls to connected clients using the function:
- nowjs.eventServerToClient
It is the data structures passed through these functions that determines the routing and handling. The functions themselves are open to extension while remaining closed to modification.
The dataContext and groupContext modules provide segregated interfaces to the server functionality. These populate the traffic "kind" attribute with "data" and "group", respectively. Conceivably, other new modules could be developed that make use of the server proxy conduit, without ever needing to change the server module. This is a great example of OCP.
Hacking nowjs to reference socket.io locally
This last bit is to show a bit of hackery I put together that allows nowjs's reference to socket.io to resolve to the client's /lib folder instead of the default of being network served by the nowjs host. There are a few reasons you might want to do this, mostly I guess involving testing and efficiency. Follow this recipe for the hack:
Todo: better AMD support for locally hosted socket.io.js so it will be built by r.js correctly.
- While viewing your nowjs site in Google Chrome, hit F12 to bring up your Developer Tools and switch to Sources view.
- Find socket.io.js listed under your server's name or IP and click it to view it.
- Right click it and choose Save As... and save it to your app's /lib folder or equivalent.
- Apply the Hack to your copy of now.js as shown in this SmartJs checkin.
- Re-run your app, being sure to clear the Js cache
- You should now see the socket.io.js listed under /lib in Chrome's Developer Tools Sources tab
Todo: better AMD support for locally hosted socket.io.js so it will be built by r.js correctly.