Options For Building Real-time Apps in Javascript

I remember when I was young, in the early 2000s, we used to check cricket scores on the ESPN sports website. That web page used to refresh automatically every 10 seconds to serve us the real-time score without us touching the keyboard And, we were happy. However, when it’s the final match, it is hard to wait even for 10 seconds.

Technology has come a long way. Now the apps are so responsive that you can even see if a person on the other side is typing the comment on your post.

Today, there are so many Javascript libraries available that can help you build real-time apps. There are two main approaches to implement this functionality:

  1. Client Pull
  2. Server Push

Client Pull: Here the client asks for updates at certain regular intervals. Similar to the ESPN example above where the page refreshes every 10 seconds, here an API call is made at fixed intervals to request data from the server. This technique is also called polling.

Here is some sample javascript code for this technique:

This kind of implementation is simple, however, it’s not really real-time. The client and server are not in sync and there is a fixed time delay. And what if there is no update from the server-side? The client will make unnecessary API calls.

There is another kind of polling that is actually real-time, called Long Polling

In Long polling, the client establishes a connection during the page load and it keeps the connection open for a long time till it someone disconnects from the webpage, and whenever a server event happens the client is notified with no delay. But there are certain drawbacks to this technique:

  • It is complex to implement
  • Not every browser supports this feature. (IE 11+)
  • It uses huge server resources and there is a limit to the maximum number of open connections

Server Push: Here the server is proactively pushing updates to the client. It is a complete reverse of the client pull. This is the most commonly used technique for all real-time applications. Below are some of the options to implement this kind of architecture.

Web Sockets

Unlike polling, where the client requests an update from the server, web sockets provide two-way communication between client and server. The client-server handshake is achieved using the WebSocket protocol instead of the HTTP protocol. Here is the typical server-side code of WebSockets:

And here is an example of the client-side code:

The application code in the browser does not have to deal with keeping the connection alive and can just assume that either the server or the browser will make sure that they exchange pings/pongs. Raw WebSocket code, with different kinds of updates, can become really long and complex. Fortunately, there are plenty of libraries available that abstract WebSockets even further so you don’t have to write any of this. Here are some common libraries:

  1. Socket.io
  2. Emitter.io
  3. Pusher

Socket.io: The bidirectional channel between the Socket.IO server (Node.js) and the Socket.IO client (browser) is established with a WebSocket connection whenever possible and will use HTTP long-polling as a fallback. In short, best of both worlds, long-polling and WebSockets.

Here are the features provided by Socket.IO over plain WebSockets:

  • Reliability (fallback to HTTP long-polling in case the WebSocket connection cannot be established due to firewall or corporate proxies).
  • Automatic reconnection.
  • Acknowledgments for transmitting data.
  • Broadcasting to all clients or to a subset of clients.

Pusher: It is an amazing platform that abstracts the complexities of implementing a Real-time system using Websockets or Long Polling. It is a paid hosted API service though. Pusher works as a real-time communication layer between the server and the client. It maintains persistent connections to the client using WebSockets as new data is added to your server. If a server wants to push new data to clients, you can do it instantly using Pusher. It is highly flexible, scalable, and easy to integrate.

When your application becomes big and broadcasts thousands of real-time messages to the client and it is hard for you to maintain the number of WebSocket connections and a messaging queue, think of using Pusher. Pusher is popular among chat-apps, multiplayer online games, and live-data visualizations. Here are some of the advantages of using Pusher:

  • Immediately scale to billions of messages
  • Industry-leading uptime
  • Flexible and versatile API
  • SDKs and libraries for every language

Emitter.io: Emitter provides a messaging pattern where senders of messages, called publishers, sends messages to Publish-Subscribed channels. Receivers, called subscribers, each receive a copy of the message in real-time. This decouples sending and receiving, giving you all the advantages of asynchronous communication.

The real advantage of this service is that the published messages can be stored for a period of time on their servers and sent to subscribers on-demand. This ensures that the applications will never miss a message, even if they were not connected when the message was sent.

Here are some of the other advantages:

  • Supports message storage with history and message-level expiry.
  • Provides secure channel keys with permissions and can face the internet.
  • Shared subscriptions, links, and private links for channels.
  • Easy deployment with Docker and Kubernetes of production-ready clusters.

I personally like the pusher. It is really easy to use. It is paid, however, I don’t need to think about WebSocket infrastructure and the scale of my application.

Thanks for reading.

Here is the draft link where I mentioned all the resources:

Resources:

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store