tags:

views:

191

answers:

8

Pretty normal scenario:

  • I have a report with a large number of rows (>2000) to be rendered as an HTML table.
  • I am paging the results on the client (browser) side.
  • I want to render the first page as quickly as possible, the rest will continue to download as JSON (about 1MB total)

I want to use a single request to the server because the database query is expensive (and I don't want to cache anything on the web server)... so I am thinking of using Comet or flushing just the first page's data, then flushing more script tags for the rest of the data.

Is this feasible? Are there any tutorials/examples of this?

Thanks.

+2  A: 

Quite feasible; however I'd do it by making two calls.

On a lower-level protocol it'd be easy to flush but I recall something funny about flushing json.

Joshua
How can I do this without caching results on the server (and avoid making two db calls?)
Jeff Meatball Yang
Maybe this will work someday: http://www.websockets.org/
Joshua
A: 

Using Comet will actually use two connections (one for getting the first page and one for downloading the rest), but what you could do is, as you say, flush the output after the first page and then continue to flush every once in a while until your entire document has been downloaded. You could also use GZIP encoding, which will make download a little faster, though it will add to server and client overhead and I'm not sure you can use output flushing with it.

hatkirby
+1  A: 

A HTML table, from a rendering perspective from my understanding is a blocking process. The browser will not start rendering until the last

</table> 

tag.

What you could do is use AJAX, to first pull the data asynchronously, into an hidden div, then when the data is finished simply add the table closing tag and make the div visible.

Edit 1:

I would highly suggest you have a look at the following link, you should be able to adapt that example for your needs.

In that example I would modify the following line:

  xmlHttp.open("GET","GetWeather.aspx?City=" + city,true);    

to your own url and query string. Then modify the following line:

if(xmlHttp.readyState==4)
   {       
       //show contents of the response using responseText property of xmlHttp obj
       document.getElementById('dvWeather').innerHTML = xmlHttp.responseText;
    } 

Such that you append to the existing HIDDEN div, then make that div visible (e.g. use Jquery)

Darknight
Thanks, I already have the <table><tbody></tbody></table> structure on the page. The part I don't know is how to get the first results from the SQL call and send them from the server - not sure how to push those first results to the client and then still send the rest without caching results on the server. (I don't want to do that)
Jeff Meatball Yang
Added more detail please review...
Darknight
+1  A: 

Divide your first page in two parts,

  1. UI
  2. Web Service

UI will load instanteously and once loaded, UI can trigger web serivce call, which can download data in ranges. ASP.NET AJAX Library can be used to load web service from same server.

Akash Kava
+1  A: 

The flush/comet approach to described should work.

You could also do it by making a single Database call, but 2 HTTP calls. On the initial page load, get the ResultSet and save it to the Application.Cache or Session. Output the first "page" of results to the browser. When the browser is finished getting the first page, make an AJAX call to a WebService (or use an UpdatePanel/Timer with one tick) that will get the remaining records from the Application.Cache/Session, minus the rows you've already retrieved. Last, clear the Application.Cache/Session.

o6tech
I don't want to use server caching - it is error prone (remote debugging, environment setup variability, etc) and I don't want the browser to make two round trips - these are remote offices with slower connections.
Jeff Meatball Yang
In that case, I think a comet approach is really your only option. I've done this in the past but it was a long time ago. It works, but I remember hitting issues with the maximum number of connections per server with IE (I believe the default is 2). From what you described, it doesn't seem like that will be a problem for you. The only other thing I remember is that there was a minimum number of characters needed for a Response.Flush to write out to the browser, so I had to send down some white-space first.
o6tech
@Jeff Meatball Yang: If the total is about 1 MB, the overhead of the second request would be negligible.
Douglas
+1  A: 

The new image search that google provides appears to do almost exactly this! It will download links to 1000 images, encoded in script at the bottom of the page, and does page/scroll client side. Works in firefox, my IE gets the old version of the page. Test it at: http://www.google.com/images

jdv
+2  A: 

Change server side interface to accept from and to params, so that you have control over how much gets fetched. Make/change a spoc in SQL to do efficient paging on SQL side (paging part will look like Row_number() OVER(order by MyColumn)). That will actually make first query much faster end-to end (SQL will be sending less that 5% of data - say 100 rows). Then in the second query you can get all the rest or you can split it in 2 or more parts (SQL server is happier sending non-giant blocks as well - efficient paging is relatively new feature - like 5yr old).

ZXX
A: 

You could use a web socket ... request the first 100 or so of the result set, render the table, and then send a second message to collect the rest of the data to be stored in a JSON array. Only involves one DB call.

Graham Chiu