views:

3474

answers:

4

I am having a problem with jQuery AJAX calls on IE7. This simple code works fine on FF and Opera. But on IE7 it takes 3-5sec. - that's 20 times slower than FF! Loading content is pure HTML and inline JavaScript code. No JS rendering. I even turned of the inline JavaScript code. Bu still slow.

$('#block').load('some url');

How to overcome this problem ? Any help would be greatly appreciated.

+4  A: 

How to overcome this problem ? Any help would be highly appreciated.

Detect IE7 on page load, and provide a discrete suggestion that users who don't like slow loading should upgrade.

Shog9
+2  A: 

There's really not much you can do. IE's javascript engine is way way slower than any of the others (in fact, it sucks). You can try out IE8. It is better... marginally...

KyleFarris
Actually, IE8 is far faster - and in some aspects, faster than FF3 believe it not. Perfect example is StackOverflow. I have about 21 tags of "interest", and IE7 rendered SO so-slowly... FF was far better. When I upgraded to IE8, IE8 screams on stackoverflow now. To the point that Firefox IS slower on SO now. So, I'm back to IE on SO. :)
eduncan911
Now try it on Safari 4 or Chrome. You're right, though. FireFox has been disappointing me recently (except for when developing because of Firebug... what would we do without that thing??). IE8 added the developer toolbar, which is loads better than, uh, nothing... but, it's still not Firebug. Sorry for the OT rant.
KyleFarris
The developer toolbar has been around since IE6
John
@John: not built-in.
Shog9
+4  A: 

I had the same problem with the slow jscript ie7 engine. I added a status popup window for the human. I update the status window as the JS proceeds in chunks. Pseudo code:

  1. Create a status container using your favorit js library. I prefer YUI. See their container api.
  2. Do some of your data load. -- you'll first need to split it into chunks
  3. Update the status popup. (Increment the % load completed, increase a bar indicator, etc.) Note that the screen probably won't change at this point since your JS thread is still running.
  4. Next, call
var t = setTimeout("next_step(2)", 0);
// Where arg of 2 would mean do the second step
// This will yield to the browser, and the display will then be updated.
// If you want to maintain the value of "this" in the function, then do
// something like
var t = setTimeout("next_step.call(MyContext, 2)", 0);
// using call to set the function's context.

Bottom line is that the user will see something changing on the screen. Note that the step of yielding with a timeout of 0 takes quite a while, relatively speaking. So my code tests the browser and does more work per chunk if it's anything other than IE.

It is very important to provide changing feedback to the user. Otherwise they think it is taking longer than it really is.

HTH,

Larry

Larry K
I've had this issue many times myself and have implemented the same "pseudo" threading technique in your answer. So often I had to build a Queuing mechanism. jQuery 1.3 implemented a Queue which can make this alot easier to work with http://docs.jquery.com/Effects/queue
Chad Grant
Excellent suggestion. There should ALWAYS be some sort of feedback when doing async calls or possibly very intensive algorithms that might take more than a second (even if it's just a 'loading' animation). This goes for any browser/implementation though.
KyleFarris
+2  A: 

I'd have to see the actual code but faced to a similar problem I had to get rid of jQuery.load(). Instead, I used jQuery.get() with "html" data type and wrote my own callback, where I injected the data via .innerHTML. Doing so, I also hit another bug (it was a <select> tag and IE won't allow .innerHTML on it) so I wrote an ugly workaround.

Resulting code was something like this:

// Fetch data (GET method allows me to use browser cache)
$.get(url, get, function(htmlValues, txtStatus){
   that.populateSelects(htmlValues, that.selectContainers);
}, "html");


// Create <select>
var select = $('<span><select disabled="disabled"></select></span>');
$("<option>").attr("value", "").text("Loading...").appendTo(select.find("select"));


// Populate <select>
that.populateSelects = function(values, selectContainers){
   var span, select, tags;

   for(var i=0, len=selectContainers.length; i<len; i++){
      span = selectContainers[i];

      if($.browser.msie){
         tags = span.innerHTML.match(/^(<select[^>]+>).*(<\/select>)$/i);
         span.innerHTML = tags[1] + values + tags[2];
         select = span.firstChild;
      }else{
         select = span.firstChild;
         select.innerHTML = values;
      }
      $(select).removeAttr("disabled");
   }
}
Álvaro G. Vicario
Cheers for this, I've just managed to shave a couple of seconds off my app's loading time by replacing the $.load with the $.get + innerHTML.
Gavin Gilmour