jquery .js loading long delay
Using jquery.load()
to replace the content of a div everything works great, however there is a major performance issue. The page loaded into the div contains some external JavaScript files and using HttpWatch
I have observed the following:
0 0 GET (Cache) text/javascript <host>/js/file1.js
0 开发者_StackOverflow 0 GET (Cache) text/javascript <host>/js/file2.js
0 0 GET (Cache) text/javascript <host>/js/file3.js
...
etc.
and a little further below (during the same load()
):
571 129862 GET 200 text/javascript <host>/js/file1.js?_=1263399258240
569 26439 GET 200 text/javascript <host>/js/file2.js?_=1263399258365
572 14683 GET 200 text/javascript <host>/js/file3.js?_=1263399258396
...
etc.
The same scripts seem to be loaded again for some reason. Even worse, there appears to be a freeze in the browser just before the files are fetched again.
Can I prevent jQuery from loading the files again? This whole issue is causing around a 5-sec delay to my page. Also, what is the meaning of the _=1263399258240
?
jQuery has three different cache options. The default null
allows caching for all requests except scripts and json requests, whilst true
and false
apply to all requests. As far as I can tell, you cannot provide an options argument in the load()
method, so you need to change the global jQuery ajax options.
I've given different ways to do this below.
- The first attempts to retain the previous global option after your request is complete (but does have its drawbacks).
- The second disregards the default setting and just sets the option so that you always allow cache to be used for ajax results (if this is not an issue for you, I'd recommend this one, as it's the simplest, with no hidden pitfalls), and
- the third example is if you want to allow caching of scripts, but not other ajax requests.
Example 1:
My first example shows how to do this if you want to revert back to normal settings after the load() request:
//first store defaults (we may want to revert to them)
1: var prevCacheVal = $.ajaxSettings.cache;
//then tell jQuery that you want ajax to use cache if possible
2: $.ajaxSetup({cache: true});
//then call the load method with a callback function
3: $(myDiv).load(myURL,function(){
/* revert back to previous settings. Note that jQuery makes
a distinction between false and null (null means never
cache scripts, false means never cache anything). so it's
important that the triple-equals operators are used, to
check for "false" and not just "falsey" */
4: if (prevCacheVal === false) $.ajaxSetup({cache: false})
5: else if (prevCacheVal !== true) $.ajaxSetup({cache: null});
//else prev was true, so we need not change anything
6: });
Important Note that in doing the above, you need to be careful you're only sending one request at a time, as storing and switching the "default" each time could lead to race conditions. If you need the above functionality and ability to send parallel requests, you'd be better off writing your own wrapper for the jQuery.ajax()
method so you can pass in the cache
option on a per-request basis. This would be similar to Andres' suggested approach below, but with the fixes I suggested to specify cache: true
and to use jQuery.html();
rather than innerHTML
. However, it gets more complicated than that, because internally, jQuery.html();
requests scripts using the global option, so you'd also need to override some of the internal functionality deep within function calls that html();
makes - not something to be done lightheartedly, but certainly possible.
Example 2: (recommended for the original question asker)
Now, if you don't care about restoring defaults, and want cache to be on for all ajax requests, you can simply call $.ajaxSetup({cache: true});
and call load()
as you previously did:
$.ajaxSetup({cache: true});
$(myDiv).load(myURL);
Example 3:
And if you want the myURL to not be loaded from cache (let's say its dynamic), but do want to cache the scripts, you'll need to add a unique-ish/random query to myURL, such as:
$.ajaxSetup({cache: true});
$(myDiv).load(myURL + "?myuniquetime=" + Date.getTime());
/* getTime() is milliseconds since 1970 - should be unique enough,
unless you are firing of many per second, in which case you could
use Math.random() instead. Also note that if myURL already includes
a URL querystring, you'd want to replace '?' with '&' */
A possible solution to this issue would be to do something:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<title>test</title>
</head>
<body>
<div id="load1"></div>
</body>
</html>
<script>
$(function(){
$.ajax({
type: "GET",
cache: false,
url: "load1.html",
success: function(data){
$("#load1")[0].innerHTML = data;
}
});
});
</script>
load1.html:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="js1.js"></script>
</head>
<body>
<div>html 1</div>
</body>
</html>
精彩评论