Periodic Ajax Status Updates

I’m working on a product at the moment that executes an Ajax request that can take up to 1 minute to return. I wanted the UI to be responsive for this period, yet notify the user that the request was still progressing.

In the past, have used a Comet library but for this product, I needed something more lightweight and with less requirement to configure the web server. So, I’ve come up with this method which uses a hidden object to execute the request and contain the result. I have a javascript poller which periodically checks the content of the object and if there is new content, it uses this as a progress message.. Works quite well for me but I’m not sure if it will scale well, what follows is an extremely cut down form of this with no error checking and is not for production use but will certainly give you a base to create this yourself.

The server side of this was originally coded in python, but due to the restrictions some people will have in running it on their host, I recoded it in PHP. I’ve included the python source in the tarball though and in the demo link below so you can use that if it suits you better. The server side is trivial anyway so you can adapt this to any language you like.
::Update, I changed the
Download source
View Demo

HTML code

<div id="response">Waiting for data</div>
<input type="button" onClick="getMeSomeData()" value="Gimme python" />
<object width="0px" height="0px" id="response_object"></object>

Easy peasy, just a div called “response” which will hold the data we get back, a button to initiate the requiest and a hidden object which will act as a kind of a proxy between our data service and the javascript.

Javascript

$(document).ready(function() {
    $("#response").hide();

    getMeSomeData= function(){
        var qryUrl = "service/LongRunningService.php";
        $("#response_object").attr('src', qryUrl);

        $("#response").show();
        pollTimer = setInterval(function() {
            var newResponse = $("#response_object").contents().text();
            var curResponse = $("#response").html();
            //ok we have a response, compare it to last response and see if there is new content
            //just compare length, too expensive to compare content
            if (curResponse.length != newResponse.length){
                //split the string using the | delimiter and take the last element
                //this is our most recent response
                var messages = newResponse.split('|');
                if (messages.length != 0){
                    //new message, let's split it into response code and message
                    var curMessage = messages[messages.length-1].split('%');
                    var result = curMessage[0];
                    var message = curMessage[1];
                    if (result == 0){
                        $("#response").html(message);
                    }else{
                        $("#response").html("Finished, result was: " + result + " - " + message);
                        clearInterval(pollTimer);
                    }
                }
            }
        }, 1000);
    };
});

So this little fella sets the src tag of the object to be the URL of our service. This makes the object call the service and receive the data as the service sends it. the pollTimer function periodically checks the contents of the object and reads the last message from the response_object (the messages are of the form “code%message” and each message is delimited by “|”).
We check the result code and if it’s 0 we have more data to come, of it’s non-zero we’re done and can proceed accordingly.

So, here’s the server side. No explanation required, it’s pretty self explanatory..

Python..

import time
spinCount = 5

def _updateProgress(val, message):
    print "|%s%%%s" % (val, message)
    time.sleep(0.5); #give IE time to do whatever it is IE does..

print "Content-Type: text/html"
print "\n"
print "\n"

for i in range(spinCount):
    _updateProgress (0, "Waiting: %s of %s" % (i, spinCount))
    time.sleep(1)
_updateProgress (1, "All good")

And in php

<?php
    $nSpinCount = 5;
    function _updateProgress($val, $message){
        if (ob_get_level() == 0)
            ob_start();
        echo '|' . $val . '%' . $message;
        ob_flush();
        flush();  // needed ob_flush
        sleep(0.5); //give IE time to do whatever it is IE does..
    }

    for ($i = 0; $i <= $nSpinCount; $i++){
        _updateProgress(0, 'Waiting: ' . $i . ' of ' . $nSpinCount);
        //this sleep is in for simulation purposes,
        //the sleep in _updateProgress is in because IE is a dopey browser
        sleep(1.0);
    }
    _updateProgress(1, 'All good');
?>

Enjoy, download and play. And leave a comment if you like..

Update: Just noticed that it won’t work in Chrome or IE – boo urns… If anyone has any ideas, please let me know..

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">

Comment moderation is enabled. Your comment may take some time to appear.

The Periodic Something Else is Digg proof thanks to caching by WP Super Cache