views:

2508

answers:

4

I am performing a jQuery .ajax() call that returns a List<string> of IP addresses on a specified subnet. I use a [WebMethod] on an .aspx page to return the values. ASP.NET's built-in JSON serializer does the magic to return the actual JSON used in my Javascript.

I have profiled the the server-side time, and it takes about 8 msec to populate and return the list, so the server-side code is not the issue.

However, when the Ajax call is initiated, in Internet Explorer it can take upwards of 3 seconds to populate a listbox with a small list of IP addresses returned. In Firefox, the listbox is essentially populated instantly.

I'm not entirely certain where the bottleneck could be. My best guess is that the fault lies with IE6's javascript engine, but even so, adding only 255 list items should not take this much time.

Can anyone point me in the right direction as to why this is happening?

Example Code

$.ajax({
          type: "POST",
          url: $("Example.aspx/GetIPsOnNetwork",
          data: "{NetworkID: " + networkID + "}",
          contentType: "application/json; charset=utf-8",
          dataType: "json",
          success: function(data) {
            $('#ipAddresses').empty();
            // Loop through each IP address and add it to the listbox
            $.each(data.d, function(){
                var ip = this.toString();
                $(document.createElement('option')).attr('value', ip).text(ip).appendTo('#ipAddresses');
            });
          },
          error: function(msg) {
            alert('Error: ' + msg);
          }
        });
+3  A: 

It could be a rendering issue. try this

      success: function(data) {
        // Loop through each IP address and add it to the listbox
        var list = $("<select />");
        $.each(data.d, function(){
            var ip = this.toString();
            list.append($('<option />').val(ip).text(ip));
        });
        $('#ipAddress').empty().append(list.find('option'));
      },

Basically, what you're doing is loading the options into a dummy list, then you're adding the contents to the ipAddresses list.

The other thing that I changed was the document.createElement(...). If you look at the internals of $('<option />') it performs the createElement for you.

Finally I choose to append the data to the list instead of calling option.appendTo('#ipAddress'), which would have to find the ipAddress element every time.

bendewey
Good advice, when I get a chance I will try this out on Monday.
John Rasch
For the size of my collection, the speedup on this was not noticeably different from the fastest setting (i.e. modifying the .innerHtml directly), both of which decreased the loading time to under 1 sec. Thanks!
John Rasch
quicker to use a string than keep creating the option elements using jquery. Concat then append once is best
redsquare
The point here is to increase his performance by not rendering each option tag individually. This works because your building the options in memory and rendering later. The differences of appending strings or objects as the OP said was not noticeable.
bendewey
+2  A: 

I suspect it might be a difference in speed of creating the option elements in IE and adding each one by one to the DOM.

On this line

$(document.createElement('option')).attr('value', ip).text(ip).appendTo('#ipAddresses');

You could try

var optionArray = [];
for (var i= 0; i < this.length; i++)
{
      optionArray[i] = $('<option>').val(ip).text(ip);
}
$('#ipAddresses').empty().append(optionArray.join(""));

or this (data.d is an object, right?)

var optionArray = [];
var i = 0;
$.each(data.d, function(key, value)
{
      optionArray[i++] = $('<option>').val(value).text(value);
});
$('#ipAddresses').empty().append(optionArray.join(""));

You might find this article on jQuery's append() useful

Russ Cam
FYI, I see this alot where people use function(key, value). What is the reason for specifying the key, value if the 'this' object is identical to the value?
bendewey
In this particular case, there is no difference. But it is useful in cases where you would want the keys too (when iterating over an object) or want the index (when iterating over an array, which would mean that the var i wouldn't be needed). I put it in here out of habit
Russ Cam
cool, but in your scenario, can't you just use function(key), without the value, then in the code array[key] === this
bendewey
+1 - data.d is definitely an object (info on the .d here: http://encosia.com/2009/02/10/a-breaking-change-between-versions-of-aspnet-ajax/#comment-34045) because it works in both browsers, it's just slow. Also, good article on append().
John Rasch
+2  A: 

Creating elements using the recommended DOM creation methods is extremely slow compared to the non-standard yet ubiquitous .innerHTML property. I once had to update a table with about 100 rows and just like you experienced, the older the browser the slower the operation using element creation. If you can, create a dummy SELECT element and populate it with a manually a concatenated HTML string of your OPTION elements and then use .innerHTML on your dummy SELECT object. You are then free to do whatever you want with this element (using .replaceChild, etc).

While this is a non-standard way of doing element creation, .innerHTML is going to stay with us for a long, long time, and it is fast.

Salaryman
This seems to be a common recurring theme, and I thought concatenating manual HTML was the hack way to do this. I will try it on Monday.
John Rasch
+1  A: 

I've found jqueyry's append to be very slow compared to innerHTML in IE7. Firefox and Chrome seem to render at the same speed using either append or innerHTML. This may have something to do with what Salaryman was saying about DOM creation methods.

crizCraig