In our fast-paced world, it’s more important than ever to provide the content people need, right when they need it. Realtime Applications give you the opportunity to do just that for your users. It’s great to focus on keeping your users happy but have you ever stopped to think about if there was another way to make these applications?  Most programmers create their Realtime Applications with either “polling” or “push notifications”. Both methods are great, but they also have their drawbacks.

 

Polling:

Polling is when your application continually checks the back end for updates on some timed interval. This is very effective but isn’t the most efficient. The main concern with polling is that it can impact on rate limits and increases strain on the host server. In a real world example, which of the following sounds better?

Option 1: Repeatedly walk back and forth to the Post Office until new mail arrives

Option 2: Go about your business and have the mailman bring the mail directly to your house


Most people would go with option 2.


Push Notifications:

Push notifications are simple messages from apps installed on a device that wake up the handset and alert the user with a message displayed on the home or lock screen. Pushing works well for a limited number of users, and is a go-to option if you need low latency. Push notifications are also better means to maintain battery life than background processes. But sometimes you want your application to receive 'background push' notifications without any user intervention or disruption.


Another approach:

To avoid the pitfalls of Polling and Push Notifications, you can make use of WebSockets and a responsive backend. Below is a Realtime shopping list that uses PubNub’s WebSockets and Parse’s responsive backend, but you could use whatever frameworks and libraries you like. You can swap in any backend in place of Parse, such as MySQL or MongoDB. And there are plenty of alternatives for PubNub such as Socket.IO, Firebase, Pusher.com, and much more.


Download the code for the Shopping list and play around with the application.



Data flow:

Let’s use a real-world example. We have two roommates, John and Jack who need to go shopping for Jack’s birthday party

 

  1. Subscribe - John opens up the shopping list on Device A and Jack opens up the shopping list on Device B. On load, Device A and Device B are both subscribed to the same PubNub channel and both devices display a shopping list based off of the grocery list on Parse.com.
  2. REST - While Jack is shopping for groceries, John realizes that they need beer for the birthday party. John is stuck at home cleaning, but he remembers that his web app updates in real time and adds beer to the list. After John adds beer to the shopping list, a REST call is made to Parse.com with a copy of the beer object. Beer is then added to Parse’s data base.
  3. Cloud Code - Parse notices that beer was just saved to the grocery Class and has the grocery Class run its afterSave method. This afterSave method sends the new shopping list item, beer, to the PubNub channel
  4. Publish - PubNub publishes beer to the shopping list channel and both devices receive it since they are subscribed to this channel.
  5. Display Changes - Both Devices update their lists with the new item and Jack now knows to get beer for the big birthday party


Storing the data:

Storing the data is fairly simple. The application uses Parse’s API to make REST calls  which quickly stores, deletes, and edits objects.


return $http.put('https://api.parse.com/1/classes/Groceries/' + grocery.objectId, editedObj,{
    headers:{
      'X-Parse-Application-Id': PARSE_CREDENTIALS.APP_ID,
      'X-Parse-REST-API-Key': PARSE_CREDENTIALS.REST_API_KEY,
      'Content-Type':'application/json'
    }
  });








A Responsive Backend:

The cool part about Parse is the Cloud Codehttps://parse.com/docs/js/guide#cloud-code]feature, more specifically the afterSave and afterDelete methods.

These methods act much like their names suggest. After a save is made to Parse, the afterSave method is automatically triggered and the code inside of the method is run. The same goes for the afterDelete method. If you wanted to use NodeJS instead, you could create your own afterSave and afterDelete methods and just copy the code from inside the methods.


The code below is broken down with comments so you can see just how simple the server side logic can be.


Parse.Cloud.afterSave("Groceries", function(request) {
  //Initializing PubNub
  var pubnub = require('cloud/pubnub.js')({
    ssl           : true,  // <- enable TLS Tunneling over TCP
    publish_key   : "pub-c-XYXYXYXYXYXY",
    subscribe_key : "sub-c-XYXYXYXYXYXY"
});
      //Creating Object with the same information Parse used to create an item in its database
     var grocery = request.object.attributes;
     var grocObj = { "name" : grocery.name,
                     "price" : grocery.price,
                     "quantity": grocery.quantity,
                     "objectId": request.object.id
                   }


      //Using PubNub to pass that object to all subscribers as a message           
      pubnub.publish({ 
          channel   : 'jakeb',
          message   : grocObj,
          callback  : function(e) { console.log( "SUCCESS!", e ); },
          error     : function(e) { console.log( "FAILED! RETRY PUBLISH!", e ); }
      });


});


Parse.Cloud.afterDelete("Groceries", function(request) {
  //Initializing PubNub
  var pubnub = require('cloud/pubnub.js')({
    ssl           : true,  // <- enable TLS Tunneling over TCP
    publish_key   : "pub-c-XYXYXYXYXYXY",
    subscribe_key : "sub-c-XYXYXYXYXYXY"
});
     //Declaring attributes of object that be deleted. Name = delete as a flag to let `app.js` know to delete this object
     var grocery = request.object.attributes;
     var grocObj = { "name" : "delete",
                     "price" : grocery.price,
                     "quantity": grocery.quantity,
                     "objectId": request.object.id
                   }
      //Using PubNub to pass that object to all subscribers as a message
      pubnub.publish({ 
          channel   : 'jakeb',
          message   : grocObj,
          callback  : function(e) { console.log( "SUCCESS!", e ); },
          error     : function(e) { console.log( "FAILED! RETRY PUBLISH!", e ); }
      });


});








The Power of Websockets:

It’s great that Parse knows to respond to changes in the database, but these changes would go unnoticed if it wasn’t for PubNub’s use of WebSockets and their Publish/Subscribe model. The WebSockets are used to keep a persistent connection between the client and PubNub’s server where both parties can send data at any time. With these persistent connections, PubNub publishes messages (the shopping list items) to all subscribed users. This makes it easy to always keep users up to date and informed on the most current shopping list.


The Party Never Ends:

And with PubNub’s Presence, users can confidently maintain their lists offline without worrying about changes going unnoticed. PubNub Presence keeps a second open WebSocket that runs concurrent to the Publish/Subscribe WebSocket. This WebSocket keeps track of who is connected to a channel and notifies the web app anytime a user connects, leaves, or has a timeout (loses connection). When connection is lost, PubNub notifies the shopping list and updates the user's local list but waits to save the actual database updates for when connection issues are resolved.


Conclusion:

Next Time you are thinking of making a RealTime Application, don’t fret if you don’t want to use polling or implement push notifications; just set up some WebSockets and grab a responsive backend, and you’ll be good to go.