views:

367

answers:

5

i have long running task that gets called using jquery ajax. i am using the block ui plugin to show "loading". is there anyway i can send progress messages back to the client to show progress and have that updated on the block ui plugin message.

So it will show this (as the server does its work) . .

"Loading first source . . . "
"Loading second source . . . "
"Loading third source . . . "
"Parsing Results . . . "

+6  A: 

From what I've seen for the case of uploading stuff - people create a separate gateway and query it for progress info as it's only avaliable on the server side. But I think it's not the best thing in Your case.

If You want to load stuff with progress information or allow server to pop info on progress while generating output then http streaming is what You want. It's explained briefly here and covered nicely here

This was quite a discovery for me ;)

naugtur
The 2 links provided are both excellent.
Doug
+1  A: 

I only recently became aware of a project that does ajax "push". You might want to check it out:

http://www.ape-project.org/

As far as I know there are a few other projects out there doing similar things, this is the truest to: "send progress messages back to the client" where the other solution requires a request to poll for progress (still a very legitimate and good solution).

Gabriel
This project uses http streaming and is linked among others in the second link I gave. Nevertheless ape-project is a c++ server for http streaming and using it for doing one progressbar seems quite an overkill to me.
naugtur
+1  A: 

I would have each AJAX request return a JSON response containing a message, the data, and the next URL to request: {message: "Loading second resource...", data: ..., next_url: "/next_part"}

Before your first AJAX request, set the BlockUI message to "Loading...". When you get the response, set the BlockUI message to the message you get back from your AJAX call. Then make the next AJAX call to the value of "next_url", and so on, looping until you've completed all of the tasks.

If you're loading one large data set, but in pieces, you may want to do something like a progressive loading design pattern, but also set a progress message as you get each response.

Matt S
A: 

One way is to use HTTP Handlers and AJAX with jQuery.

1. Initiate Server side request

$("#btnCreateInvoice").click(function() {             
       $.ajax({ type: "POST",  url: "YourHttpHandler.ashx",
       contentType: "text/html; charset=utf-8",
       dataType: "html",  
       success: function(data) { start the block UI }
       });
    });

2. Polling

What next you need to do is to poll the server at 't' interval and get the status. For that we need to call a function at 't' interval that would initiate an AJAX call to a HTTPHandler to get the status.

$(function() {
  setInterval(updateStatus, 't');
});

function updateStatus() {
  $.ajax({ type: "POST",  url: "GetStatusHandler.ashx",
       contentType: "text/html; charset=utf-8",
       dataType: "html",  
       success: function(data) { process 'data' here and update the block UI message box }
       });
}

In your case here, the GetStatusHandler.ashx can return the complete innerHtml for status. For eg on the first call it will return 'Loading First source...', then it might return:
Loding First source...
Loading Second source...
and so on.

Aseem Gautam
A: 

What you are trying to do is something similar to Comet. Traditional ("non-comet") webservers are not designed for this kind of transaction model and is therefore not a desired solution.

My suggestion is to break up the processing in one client request per data source:

function loadData() {
   // Each call passes callback(id) as a success handler
   fireAsynchronousRequest("source1");
   fireAsynchronousRequest("source2");
   fireAsynchronousRequest("source3");
}

function callback(var source) {
   if (source == "source1") {
       updateStatus("Source 1 loaded");
   }
   else if (source == "source2") {
       updateStatus("Source 2 loaded");
   }
}

This is an example of an asynchronous solution. You can implement state handling in callback() if you need it to be synchronous.

qstebom