I’ve written about Golden Layout already, but not really what I intend to do with it. I am keeping that under wraps for the most part, but I want to talk about an issue that I needed to solve in order for things to progress.

Naturally, I need to get data into these Golden Layout panels. There’s a lot of ways to do this if you check out the official website, including through React.js and Angular. I’ve looked into both, but find Angular far too obtuse for its own good, and React.js, while technically appropriate, is just not cooperating with my development environment right now. The problem, though, isn’t really getting data into a GL panel; it’s communicating between panels, but also between panels between clients.

What I’ve settled on is a technology called SignalR. The need for something like SignalR lies with an understanding of “page state” and javascript. When you enter a URL and receive a web page, that page is sent to you by the web server as a string of raw HTML that the browser displays. Once the page stops loading, the connection with the server is terminated; there’s no more communication between the two endpoints. Since javascript is parsed on the client and can use address conventions that lead back to the site that served it, constructs like timers can be used in a JS script to ping a web server at intervals, asking for data and updating the page accordingly.

Normal javascript, only updating the client from the client

SignalR relies on ASP.NET MVC, which is a design practice that uses a “model” — the part that processes business rules — a “view” — the part you see when you enter the URL — and a “controller” — a bridge between the model and the view.

MVC with javascript. This doesn’t illustrate AJAX operations, which can use JS to contact the controller, but only from and for the calling client.

Normal javascript “polling” for a single data item every 10 seconds might not be super expensive, resource-wise, but if you poll once per second, multiplied by n number of regions per page, multiplied by c number of concurrent clients all polling the same web page…it still might not be super resource intensive, I don’t know. But it seems rather wasteful to keep pinging the server with questions when the view doesn’t really need an answer. With components present in both the controller and the javascript portion of a website, SignalR keeps the connection open between the client and the server. Unlike JS which uses HTTP to ping a server, SignalR can use the more performant WebSocket technology which can both send and receive traffic.

SignalR uses javascript to send data to the controller from the client, and then to receive data on the client from the controller. The controller also serves the view.

All this mumbo jumbo aside, what’s the bottom line? Let me blow your mind in a single GIF:

Hot WebSocket action right there.

OK, that’s not very exciting, but here’s the deal: I added a button to a Golden Layout panel using javascript (which isn’t super important to this discussion) and wired it so when you click it, it calls a method on the ASP.NET controller using SignalR. Now, normally we could fire off an AJAX request to a controller on button click, receive the result, and then take an action, but the key is that I want more than just a response.

The idea is that on the controller, processing would happen. We’ll do more than just accept a value from a button; we’ll need to take in a whole lot of data like a client identifier (which SignalR does, but we’ll need to supplement), input from the type of action we’re initiating, and info on how far we need to reach in serving the result. The controller would process the data, and then we’d have to determine who gets the data.

The first thing you turn off in a new MMO.

Consider a chat box in this context. Our view renders a list of users in the “room”, the aggregate chat, and the input box. When we enter text and hit RETURN, we want everyone in that room to see what you entered (including yourself), but only the people in that room. We’d send the text to the controller by calling the “ReceiveChatText” method which is defined in the Controller. That method would check the client list for those who are listed as being in the same room as you. The Controller then sends your text to just those clients by calling the “UpdateChatWindow” method which is defined on the Client in javascript, which adds the text you entered to the chat display of everyone else in the room.

In the GIF, once we press the button we send the name “Chris” to the controller, which doesn’t have any other clients to investigate, so it merely sends “Chris” to all clients. On the client-side, the called method adds another row to the table that is being used to display the results.

The major benefit here is that we don’t rely on polling. This is commonly referred to as “event-driven”: we only act when an event is “raised” which in this case is trigger by the press of a button. When no person is taking action, no events are being raised. Because SignalR can broadcast to everyone or just a defined subset, we can divide users into bins (like regions in a game worl…I mean, chat channels) and only push the data needed to be received to the people who need to receive it. In this case, the client JS doesn’t even update the client directly; it sends a message to the server, and the server responds with the command for the client(s) to update.

The final benefit to this over simple polling is that, should there be a server-side process that does fire off without needing any user input, it can also use SignalR to select all or some of the clients to broadcast to. This could be used to send all connected clients a message at a predefined time, or in relation to a server IT or hardware event.

Scopique

Owner and author.

Leave a Reply

Your email address will not be published. Required fields are marked *