Thursday, November 11, 2010

Ajax request keeps Google Chrome pointer spinning

I have a wonderful instant messaging app running using AJAX to maintain a long term connection to a simple HTTP server. How I did that is a discussion for another time, but the problem was that I needed to create the connection when the user first hit a web page. So I just simply put a Javascript call in body onload, something like:

<body onload="start_listener();">

Plain and simple, it worked. But on Google Chrome, the page continued to say 'Waiting for servername' and the mouse pointer was continuously spinning. I suffered this for a while, until I realized that the same call to start_listener() didn't exhibit the same endless spinning if I fired it from clicking a link.

I must be the only person on the planet with this problem, as Google yielded no results. I tried moving the call to a script at the end of the page, putting it into a script as window.onload, all to no avail. I double checked the request really was asynchronous. Chrome worked fine, but the cursor was disconcerting to say the least.

So I decided to search similar projects: node.js has nice event driven messaging demo, frequented by many observers and a handful of weirdos. They don't have the spinner problem, as they have you click on a link to get started. But something in there made me thing that I should attack this from another direction. How about I triggered an event that called the Javascript function, just as if I had clicked a link with the mouse?

Well, brainwave finally kicked in. Use a timer on the page, to start the AJAX request soon after the page loads. The Javascript must be event based, right?

So I converted my onload to:

<body onload="setTimeout('start_listener()', 1000);">


effectively triggering the call to AJAX as an event. And at last, Chrome stops spinning.

What's the deal? I guess that if you put an AJAX call directly into the main page load, Chrome treats it as an extension of the original request (maybe more through the design of the page request handling than on purpose?). But pull it out so that the AJAX request falls into a distinct event, and all works well. Timeout lets you do that without needing a user to click anything.

Finally I can look at my application without getting freaked out that it is failing to load something...

5 comments:

  1. Thanks a lot for that setTimeout trick.

    Chrome's behaviour with long running requests on page load has been bugging me for a while.

    ReplyDelete
  2. Thanks. Been looking everywhere for a solution to this problem. Much appreciated.

    ReplyDelete
  3. Just landed here searching for a solution to this problem after hand-crafting my own AJAX long-poll system. Life saver, thanks a lot!

    ReplyDelete
  4. Just found this solution while searching for the same problem - works like charm.

    I did one modification: instead of modifying the body tag I inserted the setTimeout(...) into
    jQuery's $(document)ready(function() { ...}); of my local javascript - thus I don't forget it when using other pages with different body tags :-)

    ReplyDelete
  5. Very helpful!! Works like a charm.

    ReplyDelete