11

Building a social network, I'm trying to fetch live notifications. Currently, the site sends an AJAX request every few seconds using setInterval. It looks something like this:

setInterval ( function(){
    url = base_dir+"/ajax/file.php";
    data = "data=someData";
    $.ajax({
        type: "POST",
        url: url,
        data: data,
        dataType: "json",
        beforeSend: function(x) {
            if(x && x.overrideMimeType) {
                x.overrideMimeType("application/json;charset=UTF-8");
            }
        },
        success: function(JSON){
            // retrieve data here   
        }
    });
}, 5000);

That works perfectly, but I'm very worried about that creating servers overload. I tried the comet technique but for some reason it sends much more requests than the above code. Is there any other more useful technique for pushing this data live?

EDIT: For implementing long polling I used the following (used the example mentioned here: http://techoctave.com/c7/posts/60-simple-long-polling-example-with-javascript-and-jquery):

(function poll(){
    url = base_dir+"/ajax/file.php";
    data = "data=someData";
    $.ajax({
        type: "POST",
        url: url,
        data: data,
        dataType: "json",
        beforeSend: function(x) {
            if(x && x.overrideMimeType) {
                x.overrideMimeType("application/json;charset=UTF-8");
            }
        },
        success: function(JSON){
            // retrieve data here   
        },
complete: poll,
timeout: 5000
    });
})();

There's a possibility that I might not get the comet principle right.

PHP code:

// Checks for new notifications, and updates the title and notifications bar if there are any
 private static function NotificationsCounter (){
    //self::$it_user_id                                     = query that retrieves my id for further checks;                                                        
    //$friend_requests_count                                = query that retrieves the friend requests count;
    //$updates_count                                        = query that retrieves the updates count;               
    $total_notifications                                    = $friend_requests_count+$updates_count;

    if ($total_notifications > 0) $addToTitle = "(".$total_notifications.")";
    else $addToTitle = "";

    if ($updates_count > 0) $counterHTML = "<span class='notification_counter' id='updates_counter' style='float: right;'>".$updates_count."</span>";
    else $counterHTML = "";

    $data = array("counter"=>$total_notifications,"addToTitle"=>$addToTitle,"counterHTML"=>$counterHTML,);
    echo json_encode($data); // parse to json and print
}

Since Facebook uses PHP as well, how do they do it?

talhof9
  • 135
  • 3
  • 9

2 Answers2

9

You should use websockets. You can connect to the server and register onmessage handler. Whenever the server has anything to be send to client, your handler will get invoked. No timeout needed.

Check for websocket support in your browser. As of now, only Chrome, Opera and Safari support them.

if ('WebSocket' in window){
   /* WebSocket is supported. You can proceed with your code*/
} else {
   /*WebSockets are not supported. Try a fallback method like long-polling etc*/
}

Connecting

var connection = new WebSocket('ws://example.org:12345/myapp');

Handlers

connection.onopen = function(){
   console.log('Connection open!');
}

connection.onclose = function(){
   console.log('Connection closed');
}

connection.onmessage = function(e){
   var server_message = e.data;
   console.log(server_message);
}

Documentation: http://www.developerfusion.com/article/143158/an-introduction-to-websockets/

ATOzTOA
  • 34,814
  • 22
  • 96
  • 117
  • 1
    Recent versions of Firefox support sockets as well – Asad Saeeduddin Jan 01 '13 at 18:09
  • 2
    FYI, also IE10 support websocket – sdespont Jan 01 '13 at 18:34
  • @sdespont That is good news... Any idea whether Hixie is supported? – ATOzTOA Jan 02 '13 at 03:53
  • How can I implement this with PHP? – talhof9 Jan 02 '13 at 13:30
  • Well, this works great on WAMP, but after uploaded it to the server I keep getting "Address already in use" because of socket_bind() line. Tried the "SO_REUSEADDR" thing, still no luck. I googled it over and over and couldn't find a solution. Any idea? – talhof9 Jan 03 '13 at 15:35
  • Have you tried waiting for a while? You should only call socket_bind() during server startup. Is the server managed by you? – ATOzTOA Jan 03 '13 at 15:42
  • Yeah, I've waited... I'm using shared servers (just for setting the MVP up. I'll switch hosting as soon as I'll release it to the public), so I can't access the terminal. Btw, thanks for helping! :) – talhof9 Jan 04 '13 at 15:33
  • Is there anyway you can stop php service in the hosting server? – ATOzTOA Jan 04 '13 at 15:36
  • What do you mean? I have a proccess killer if that what you mean. I'm using Bluehost for now – talhof9 Jan 04 '13 at 18:04
  • turns out they do block ports, so I can't set-up sockets server, unless I'll buy a dedicated server. Bummer... Anyways, huge thanks for your time and dedication! – talhof9 Jan 04 '13 at 20:16
3

Websockets will be the way to go once they are more universally implemented across the major browsers - I would guess a minimum of 5 years.

The last I heard Facebook chat uses comet and a whole bunch of servers. If you want something more lightweight I can think of two options.

  1. Reduce the polling interval. This is strictly a UI issue - users may have a perfectly acceptable experience with intervals as long as a couple minutes. The only way to know for certain is through user testing, but polling every 5 seconds is probably overkill. No matter what you choose as the optimal interval, this does give you an quick way to scale if you are getting hammered - just crank up the interval until the servers stop melting.

  2. Use HTTP validation caching. You can make the requests more lightweight if the server only returns a response body when the content has changed since the last request. You will have to build something custom using ETag or Last-Modified headers and a lightweight modification checking system on the server, but it might save you a few bytes.

Chris Broski
  • 2,421
  • 27
  • 23
  • It's 5 years later and as I was hoping, websockets are natively supported in every major browser. I wrote the simplest example I could in github https://github.com/chrisbroski/bare-socket – Chris Broski Jun 11 '18 at 15:06