Chrome AJAX on page-load causes “busy cursor” to r

2019-02-04 14:41发布

问题:

In Google Chrome, AJAX called within $(function(){....}); seems to keep the page loading.

I have a site with a few pages with tabs. Because I'm using cheap godaddy hosting, I want the page to load as fast as possible. I thus want to load a page on 1 tab and then in the background use AJAX to load the other tabs. When I run AJAX from

$(function(){
    /*AJAX CODE HERE */
});

The cursor shows the page as loading for a long time (http://jsfiddle.net/mazlix/7fDYE/9/)

I have figured out a way (in chrome atleast) to somewhat fix that using setTimeout(); (http://jsfiddle.net/mazlix/7fDYE/8/), but this only works if you correctly predict when the window finishes fully loading and obviously makes it take longer to load. I want a way to load content via AJAX immediately after the page loads, so no "busy-cursor" is displayed while waiting for the returned AJAX.

回答1:

Google Chrome shows Loading Indicator as long as there are no new queries to servers. While the loading indicator is shown, all new requests are causing Chrome to extend the time the indicator is shown. Furthermore, when esc is pressed while the indicator is shown, all requests are aborted! These include AJAX requests and even Flash requests! Take a look at this question: i thought it was because of Youtube, but it turned to be Chrome's usual behavior.

The only way to avoid "extending" the time Loading indicator is shown, is making the requests after the loading indicator is hidden: i.e. when all queries to server are completed. JQuery's documentation on .load() says:

The load event is sent to an element when it and all sub-elements have been completely loaded. This event can be sent to any element associated with a URL: images, scripts, frames, iframes, and the window object.

So, if you're sure that there are only images, scripts and frames on your page, window.load() will be fired just when you need it. Adding setTimeout() to it will work as you like. Here is an example: http://jsfiddle.net/7fDYE/22/

If there are other requests being made before your request, you should wait for them to be completed! For example, you know that besides the images/scripts etc. you have 3 more AJAX requests before the page loads. You can have something like this:

var loaded=0,needsToBeLoaded=4; //3 AJAX + window
function onLoad(){
    loaded++;
    if(loaded==needsToBeLoaded){
         //do the AJAX request   
    }
}
window.load(onLoad);
// add onLoad() to all 3 AJAX request handlers

I'm not sure what you can do with Flash requests...



回答2:

Update

This solution will not work for Chrome. It stops the loading indicator only when all requests made before window load have completed. The only solution appears to be to get it to make the request after window load, but as far as I know, this is only possible with setTimeout, which isn't great.


Update

To get around the pointer issue in Chrome, you could set the cursor style as shown in this fiddle. It's a bit hacky and it doesn't address the issue of the loading indicator at the top of the tab.


The loading indicator will be present in browsers until the page has loaded (window's load event). In $(function(){someCode();});, someCode is executed when the DOM load event is triggered (when all content has been parsed and inserted into the DOM, before page load). The execution of JavaScript at this point blocks the window's load event from firing, and so prevents the loading indicator from stopping. Note that image loading also blocks the window's load event.

Instead, you could try $(window).load(function(){someCode();});. In this example, someCode is executed when the window's load event is triggered. This is at the point where the browser's loading indicator stops.

So, instead of:

$(function(){
    /*AJAX CODE HERE */
});

Try:

$(window).load(function(){
    /*AJAX CODE HERE */
});

Note that this may cause your JavaScript to begin execution later, which may not be desirable.



回答3:

There is a super simple, fool proof solution to this:

Wrap your function in a setTimeout call, and use an interval of 0. This will queue the function to be called immediately, but Chrome will no longer wait for it to load before considering the page 'complete'. You do NOT need to make any guesses about when the page will be complete, just make sure you're calling setTimeout inside the jquery Ready handler, like so:

$(window).load(function() {
    setTimeout(function() {
        $("#result").html(ajax_load);
        $.post("/echo/json/", {json: json1, delay: 10000}, show_json, "json");
    }, 0);
});


回答4:

According to JQuery docs, no javascript should be run till ready for example

$(document).ready(function() {someCode();});

with that in mind i changed your jsFiddle (it takes some time to load but it works)

Edit: hadnt forked jsfiddle ><



回答5:

I'm not sure I agree that this is a problem. I'd say this is a desirable behavior from chrome as it indicates that it's in fact not finished loading. I would say that Firefox is actually incorrect about not indicating that it's still waiting for a script callback to finish.

This could be a matter of personal taste (I like the browser to indicate that it's waiting/working, even if it makes my browser seem slow), in which case succeeding in "fixing" this "problem", will make the browser not behave in the way the user is used to. In web development you really should not try to force the browser to behave in a specific way that is not essential to how the webapp works, because you're likely to end up enforcing a look-and-feel from one os you're used to into another os with a different feel, making it feel more foreign to the users of another os (even if it makes the site feel more native to you).

The busy cursor is not a problem anyway, because elements already loaded, are still responsive.