views:

338

answers:

2

I want to create a section in my site, where a user has a few simple update buttons.

Each of these update buttons will be going to the server, and will do a long crunching behind the scene.

While the server crunches data, I want the user to have a some kind of progress indicator, like progress bar or textual percentage.

I'm using jQuery as my JavaScript library, and CodeIgniter (PHP) as the server-side framework, if it's important...

What I was thinking about is using PHP's flush() function to report progress status to jQuery, but I'm not sure that jQuery's Ajax functions are reading the output before it's complete...

So any advice/explanation would be useful and helpful!

+2  A: 

It's pretty hard to get this right. What we've settled on for our system is a "faked" progress bar - it just animates over and over (which since it is an animated gif, you might expect!).

An alternative would be to submit to one script, and have that processing in the background (and outputting progress to a file) while making an Ajax request to another script whose only responsibility is to read that progress file and return how far through the process you are. This would work - it feels a little bit kludgy, but it would at least solve your immediate problem.

I know very little about Comet or the likes, so this is purely based on my current understanding.

Stephen Orr
+2  A: 

I'm going to give you an example using WebSync On-Demand, but the same approach would work regardless of your choice of server.

Here's what you do. First, kick off the long-running operation somehow; your user clicks the button to start this process (I'm going to assume an Ajax call, but whatever works), and you return to them some sort of identifier, we'll call that 'myId', give it a value of '1'. Whether you do that by invoking a process of some sort, etc, is up to you.

Then, in your callback from that invocation, you would write something like so:

var myId = 1; // this would be set somewhere else
client.initialize('api key');
client.connect();
client.subscribe({
  channel: '/tasks/' + myId,
  onReceive: function(args){
    // update the progress bar
    myProgressBar.update(args.data.progress);
  }
});

What that'll do is subscribe your client to receive notification about updates to the task, so all that's left is to push out the updates, which you'd do in whatever process is actually running the task. That would look like (in PHP, using the SDK):

$publisher = new Publisher(
    "11111111-1111-1111-1111-111111111111", // your api key again
    "mydomain.com" // your domain
);

// publish data
$response = $publisher->publish(array(
    array(
        'channel' => '/tasks/' . $myId, //comes from somewhere
        'data' => (object) array(
            'progress' => '45' //45% complete
        )
    )
));

// success if empty (no error)
$success = empty($response); 

That's it; as updates occur, they'll push out to your client in real-time.

jvenema