12

I have a page where I list hardware devices we monitor for customers. Each row displayed also shows the status of the device i.e. whether it's running, paused, starting up etc.

To improve page load times I list the devices but don't query for their status until the page is rendered. This is because some queries such as via SNMP or other API's can take as much as 5-10 seconds to respond. So for a list of say ten devices it could take well over a minute of the user looking at a blank page. So I do the following instead -

On the device list page I have the following script:

$(document).ready(function () {

  var devices = $('div[name="runStatus"]');
  devices.each(function () {

    // Get device ID (I embed this using the HTML5 data-* attributes/annotations)
    var deviceId = $(this).attr("data-deviceid");
    var url = "/devmanager/status/" + deviceId;

    $.getJSON(url, function (response) {
      // Not actually important to the question...set text status, colours etc
      $('div[data-deviceid="' + deviceId + '"]').text(response);
      //...
    });
  });
});

What I'm finding is that if I allow this script to run, all links on the page become unresponsive.

I'm guessing this is because I've quite a few almost parallel async requests blocking until they get a response from the server and somehow the "UI thread" is being blocked by this?

However I thought this wasn't supposed to happen with AJAX.

I find this 'blocking' behaviour to happen in IE8, Chrome 8.0 and Firefox 3.6. Chrome in fact shows the arrow cursor + spinning-toilet-bowl-of-death (I'm using Windows 7) as if the page isn't completely rendered.

How can I fix this?

Kev
  • 118,037
  • 53
  • 300
  • 385
  • 3
    How many items are in the devices collection? You'll likely only be able to do 2 or 3 concurrent Ajax requests at once, the rest will be queued, possibly slowing down loading the rest of the page (downloading images and such). – Douglas Dec 05 '10 at 17:12
  • $('div[data-deviceid="' + deviceId + '"]').text(response); looks like a fairly expensive selector. Atleast on a larger page. If you remove all the code in the callback, and the page then runs fast, that's the reason. Worth a try! – Mikael Eliasson Dec 05 '10 at 17:25
  • @douglas, @mikael - there are 6 items in the list. Setting these values (in a for loop) happens in the blink of an eye. – Kev Dec 05 '10 at 17:43
  • I would not be surprised at this behavior if you had said the list contained 50+ items... but 6.. it's surprising that six simultaneous async request would be enough to jam up the browser/os. Can you post a link to the page in question? I'd like to see how it holds up on Safari/Mac, and have a look through the trusty old web proxy. – Lee Dec 05 '10 at 19:15
  • @Lee - I'll knock up a site you can test against. The production stuff is running behind a password protected portal so you can't get at it easily. – Kev Dec 05 '10 at 21:05
  • @Lee - odd...I built a cut back version isolating just this functionality to demo for you but that works like grease lightening. So there's something else odd going on in that page. Will go and do some head & arse scratching. – Kev Dec 06 '10 at 14:17
  • @Kev - good luck with it! Never under estimate the effectiveness of simplifying your test case. ;-) come back and let us know what you figure out. – Lee Dec 06 '10 at 16:06
  • @Lee - Oh I know...and should know better after all these years :). – Kev Dec 06 '10 at 16:07
  • @Kev - Thanks for the heads up. Interesting results. I'm glad you got it worked out. – Lee Dec 14 '10 at 04:55

4 Answers4

5

I imagine you're running into browser limitations for handling multiple requests.

Have you tried using Fiddler and looking at the timeline to see what is blocking?

This SO question will probably help:

How many concurrent AJAX (XmlHttpRequest) requests are allowed in popular browsers?

Community
  • 1
  • 1
ScottE
  • 21,530
  • 18
  • 94
  • 131
5

Turns out this isn't a problem with the client side:

Would multiple calls to the same ASP.NET MVC action cause the browser to block?

Would multiple calls to the same ASP.NET MVC action cause the browser to block? - Answer

This was being caused by a "by-design" feature of ASP.NET where multiple requests made in the same session are serialised.

Community
  • 1
  • 1
Kev
  • 118,037
  • 53
  • 300
  • 385
0

It sounds like getJSON is using asynchronous: false as an option to xhr. It kind of suprises me that jquery would use that as a default though, since that is pretty much always a bad idea for the reasons that you are describing.

Don't have the time to look into it more at the moment, but that is the first path I would take.

Matt Briggs
  • 41,224
  • 16
  • 95
  • 126
  • According to the documents $.getJSON() is a shorthand $.ajax() call and it sets async:true. – Kev Dec 05 '10 at 17:46
0

I have never had problems with $.getJSON(). It is asynchronous as far as I know. What is probably happenning is a javascript error, since you're trying to do:

$('div[data-deviceid="' + deviceId + '"]').text(response);

I'm guessing there is an error here because response is a javascript object or array, not a string. What you should do is text(response.desiredProperty) or text(response[index]) according to the type of object response is.

Since javascript errors sometimes make our browsers behave unexpectedly, this MIGHT (only might) me your problem.

Marcelo Zabani
  • 2,139
  • 19
  • 27
  • It's not a javascript error. Also response is a string..trust me. I checked all this in Firebug/Chrome dev tools. The problem is definitely to do with the async calls. And you're right, $.getJSON is an async shorthand method for calling $.ajax(). – Kev Dec 05 '10 at 17:40
  • Additionally...when I comment out the line with `$('div[data-deviceid="' + deviceId + '"]').text(response);` the problem remains. – Kev Dec 05 '10 at 18:14
  • Interesting... I just thought this could be the problem but it turns out I'm completely wrong. This problem leads us to ScottE's answer, which is very interesting and could happen in a lot of different situations. I'll be checking this again to see what you did to solve/workaround this problem. – Marcelo Zabani Dec 05 '10 at 20:27