Polling with Javascript & jQuery

In a previous post, we learned how to use the publish-subscribe cycle along with Faye and the Private Pub gem to create a chatting application with Rails.

There is, however, another way to provide your users with push notifications from the server--polling.

What is Polling?

The web is built on the client/server model--the client senda a request to the server and the server sends information back to the client. In this model, there is no way for the server to indepedently send information to the client. So, how can a client receive real-time updates from the server? Aside from the publish-subscribe method mentioned above, many real-time web applications utilize polling.

The client client can periodically "poll" the server and request new information (such as new messages or emails). The server then responds and sends the new information down to the client. The operation is then repeated. This effectively imitates the action of a server "publishing" information to a client.

Polling does have some drawbacks. From PubNub:

As usage grows, how will you orchestrate your realtime backend? When mobile devices rapidly switch between WiFi and cellular networks or lose connections, and the IP address changes, does long polling automatically re-establish connections?
With long polling, can you manage the message queue and catch up missed messages?
Does long polling provide load balancing or failover support across multiple servers?
When building a realtime application with HTTP long polling for server push, you’ll have to develop your own communication management system. This means that you’ll be responsible for updating, maintaining, and scaling your backend infrastructure.

However, for the purposes of a small-scale application, polling is a perfectly sufficient way to update clients with important information in real-time, and many large-scale applications do utilize effectively.

Why Use Polling?

In the example of my Title-ize! application, we need a way for user's to be notified when someone is messaging them to play a new game. If a user is already in a particular chat room, this isn't an issue. They'll simply see the new messages published to that chat because we built it using the publish-subscribe model. However, if they are on their home page that displays the lists of players, they need to be alerted if a particular player is initiating a game with them by sending a new message.

Let's say, for example, that Charlie Kelly of Paddy's Pub is trying to send me a message. It is probably very important--it may even have something to do with the eight cats that live in his sink.

How can I get my application to alert me about his new message? Ideally, Charlie's name on my list of friends will become bolded and the green light next to his name with flash red.

Let's make it happen:

Setting Up Polling

Before we start coding, let's outline what we need to achieve here:

  1. Fire a request to the server at a given interval to check for new messages.
  2. If there are new messages sent to the current user, apply some "alert" styling to the sender of those messages on the above list.
  3. Do it all over again!

The setTimeout Function

The setTimeout function is a Javascript function that triggers certain code to run at the end of a set interval. It takes in two arguments, the callback function you wish to execute at the end of the interval, and the amount of time you'd like to set that interval equal to.

We can use the setTimeout function recursively to achieve polling:

$(function() {
  setTimeout(updateMessages, 10000);
});

The above function, set to fire on document ready, will wait 10 seconds and then execute the updateMessages function. But wait a second, you are probably thinking, don't we need to check the server for new messages every 10 seconds, not just once after a period of 10 seconds? You are so smart, that is absolutely correct.

Let's take a look at that updateMessages callback function:

function updateMessages () {
  $.getScript("/conversations.js")
  setTimeout(updateMessages, 10000);
}

First, we use the jQuery getScript method to load a JavaScript file from the server using a GET HTTP request and then execute it. Then, we recursively call the setTimeout function again. Thus, we are executing the function every 10 seconds.

How is this actually updating our view to reflect new messages? Let's take a look:

$.getScript

As I mentioned above, getScript is loading a js file, in this case /conversations.js. This reflects the javascript file that the index action of the Conversations controller renders.

class ConversationsController <     
 ApplicationController
  before_filter :authenticate_user!

  def index
    @decorated_conversation = 
      ConversationDecorator.new(current_user)
  end

The index action above instantiates a new instances of our ConversationDecorator class, a decorator responsible keeping track of conversations between users. This decorator is built to include some instance methods that will tell us if there are any new messages sent to a current user.

Then, the index action renders the index.js.erb file in the conversations subdirectory of the views directory.

index.js.erb:

<% if @decorated_conversation.updated? %>
  <% @decorated_conversation.convos.each do |convo| %>
      var id = <%= convo.sender_id %>
      $('#new-messages-'+ id).html("");
      $("#new-messages-name-"+id).addClass("bold-name")
  <% end %>
<% end %>

First, we check if there are any new messages by calling .updated? on our instance of the ConversationDecorator class. If there are new messages, we collect them with the .convos method, iterate over them and add our "alert" styling to the appropriate sender's name on our list of players.

And that's polling with Javascript and jQuery. If you're interested, you can check out my repo for the project we discussed here.

Now, next time you need a good bird lawyer, Charlie will be sure to get your message.

subscribe and never miss a post!

Blog Logo

Sophie DeBenedetto

comments powered by Disqus
comments powered by Disqus