views:

54

answers:

1

I am doing a jQuery $.get to a html file, and in the success function I filter on a select block and take the options apart, rendering the text of the selects as paragraphs in divs that I append in my markup. Getting and rendering the selects takes a while (there are about 8000) but I was expecting the div's to show up one by one and letting me work on them (I assign click and hover events to them with .delegate ...), but they show all up at once and my browser window is blocked. I even explicitly set async: true with an $.ajaxSetup before the $.get (which should not be necessary as it's the default). I must be missing something fundamental but have no idea what ... Thanks in advance for ideas and tips.

+1  A: 

You should load the results in smaller chunks. In pseudocode it will be something like this:

loadDataUsingAjax(url, index) {
  load the first index to index + 250 items async using an ajax call;
  if there are still more items
     a few mili seconds later call loadDataUsingAjax(url, index + 500);
}

loadDataUsingAjax(url, 0);

Otherwise most browsers, especially on slower computers, will freeze for a few seconds while they try to update the DOM.

UPDATE: Actual jQuery code

var CHUNK_SIZE = 500;
var DELAY = 100;

function loadDataUsingAjax(ajaxUrl, index) {
  $.ajax({
    url: ajaxUrl,
    data: {startIndex: index, chunkSize: CHUNK_SIZE},
    dataType: 'json',
    success: function(response) {
      // response is in JSON format
      // convert it into HTML and add it to the appropriate location in the page
      // response.hasMoreResults indicates whether there are more items in the result set
      if (response.hasMoreResults) {
         setTimeout(function() {
            loadDataUsingAjax(ajaxUrl, index + CHUNK_SIZE);
         }, DELAY);
      }
    } 
  });
}
loadDataUsingAjax("yourUrl", 0);

Your server side script should do something like this:

startIndex = get the value of the startIndex request parameter;
chunkSize = get the value of the chunkSize request parameter;
// MySQL query
select ... from ... where ... limit startIndex, startIndex + chunkSize;
create a json result from the MySQL result set;
select count(...) from ... where ...;
if count(...) is > startIndex + chunkSize then set hasMoreElements = true
Bytecode Ninja
So what you are saying is that it's not the ajax call but the insertion of the 8000 elements that is stalling the browser? I have a MacBook Pro with a 2.8GHz Intel Core Duo and 4Gig of memory, so I would not necessarily say this is a slow computer. I thought the whole idea of asynchronous ajax calls and DOM manipulation is that is does _not_ block the browser window.I will try your suggestion - any ideas of how I could translate the pseudo code to Javascript/jQuery?Thanks.
zwalex
Yes, adding a lot of DOM elements at once to the page can freeze it for a few secs. The async call only prevents the browser from freezing while the call is in progress. The actual DOM insertion won't be performed asynchronously. I will update my answer to turn the pseudo code into real jQuery code.
Bytecode Ninja
> "Your server side script should do something like this:"Well there's the problem - there is no server side script or at least not one that I could influence or change at the moment. My only interface is the nasty html.I guess I am going to suck in the whole page and do the DOM insertion in chunks then.Thanks for your tips though!
zwalex
"I guess I am going to suck in the whole page and do the DOM insertion in chunks then." I was actually going to suggest you to do this, as in your particular case you're going to show all the 8000 elements anyway and fetching all of them at once but inserting them in smaller chunks with a small delay between insertions makes more sense. By the way, in StackOverflow it's a good thing to upvote helpful answers... :)
Bytecode Ninja
> "it's a good thing to upvote helpful answers... :)"I know ... I am just still missing the necessary reputation points to do so ...
zwalex
> "I am just still missing the necessary reputation points to do so ... "but now I have! Thanks Bytecode Ninja!
zwalex