How does jQuery disable AJAX caching? - javascript

To disable caching files from ajax requests, you can use jQuery's
$.ajaxSetup({
cache: false
});
But how does jQuery do this? I know jQuery is a javascript library, so whatever can be done with jQuery can be done with plain javascript. So my question is: What is the javascript code that jQuery uses under the hood to turn off ajax file caching?

This is the source of the cache
if ( s.cache === false ) {
s.url = rts.test( cacheURL ) ?
// If there is already a '_' parameter, set its value
cacheURL.replace( rts, "$1_=" + nonce++ ) :
// Otherwise add one to the end
cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
}
s is ajax's option,
If you set cache false, It will add a search to you request url,
The 'nonce' is jQuery.now(), It's a time;
So browser will not user cache when you send ajax , request url always differenrt.

I think that Today's Browsers use onunload = function(){} just like that (yes, exactly) to prevent the Browser from caching a web page, as it was when you left it to go to another page.
It's important to under stand, however, that that is not the same as the Browser's ability to remember the JavaScript loaded from your <script type='text/javascript' src='somePage.js'></script> tags when they have that src attribute. If you change your JavaScript on a live site, you'll want to change the name of that file, or, if the Client has not cleared their cache their Browser will attempt to load the file as it remembers it.

The easiest way to shut off browser caching of Ajax requests is with a query string parameter based on time.
var t = new Date().getTime();
console.log('some-url?_='+t);
This yields the following query string
?_=1481683928873
The browser will see this as a different request (assuming it only makes one per microsecond) and it will request the content from the server, rather then serving it from its cache.

If you read the docs they say:
cache (default: true, false for dataType 'script' and 'jsonp')
Type: Boolean
If set to false, it will force requested pages not to be cached by the browser. Note: Setting cache to false will only work correctly with HEAD and GET requests. It works by appending "_={timestamp}" to the GET parameters. The parameter is not needed for other types of requests, except in IE8 when a POST is made to a URL that has already been requested by a GET.

Related

JavaScript img.src onerror event - get reason of error

There can be different reasons for <img> load errors, such as network error response, bad image data...
error object received from onerror doesn't seems to specify the exact reason.
Is there a way to know if the error is because of a network error, say HTTP 500 or a network timeout?
EDIT:
I'm not looking for an alternative way to load a resource, such as AJAX request. I need an answer specifically for <img> tag with onerror event. The reason for that is that I'm using this method for pixel-tracking and I need a way to retry on upon network errors. I'm also not looking for alternative tracking methods such as JSONP.
Edit 16Nov16 2020GMT
Maybe you are pixel-tracking in emails or other clients limited in Javascript capabilities.
One idea that comes to mind is to use URL query paramters in your <img>'s src URL.
With regards to network timeouts, I will pose the idea that a user opens an email, loads the email entirely, then disconnects from the internet and somehow this does not give the tracker enough time to load.
https://developer.mozilla.org/en-US/docs/Web/API/WindowTimers/setTimeout
I would suggest to use setTimeout() inside your onerror function.
This will continue attempting to set/load the <img>'s src URL. You could append the seconds it took until successful load to the URL of your src file as a query parameter like ?s=<sec>
As far as determining status 500 codes on image loads you might want to consider creating a custom 500 error file which would then create -- for example -- a MySQL database entry with all sorts of information you have access to and if you chose to use the query parameters mentioned before then you have slightly more information added to the error.
onerror for <img> gives limited information about the network
The information that is available from <img> can be found at
https://www.w3.org/TR/html/semantics-embedded-content.html#htmlimageelement-htmlimageelement
Older answer:
Perhaps a route you would like to try is to use AJAX to load the image data and set the <img> src to the base64 of the image data received. I hope this helps.
Edit 14Nov16 2018GMT
Alternatively use AJAX to determine if the image loads properly and then use the same URL sent to AJAX as the src for your <img>. It would of course be redundant but would avoid the issue of long "data" URLs.
Edit 15Nov16 0832GMT
Also regarding Network Timeout I found this thread to be useful JQuery Ajax - How to Detect Network Connection error when making Ajax call
Apparently you can specify a timeout to AJAX much like using error except you just provide the miliseconds manually.
Converting to Base64
https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding_and_decoding
https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/btoa
var encodedData = window.btoa("Hello, world"); // encode a string
Or if you are concerened about older browsers able to use btoa() then you might be interested in Google's https://chromium.googlesource.com/chromiumos/platform/spigots/+/refs/heads/firmware-u-boot-v1/base64_encode.js
Status Code checks in jQuery's AJAX
jQuery: How to get the HTTP status code from within the $.ajax.error method?
$.ajax({
type: 'GET',
url: '/path-to-my/image.png',
data: null,
success: function(data){
alert('horray! 200 status code!');
// convert to base64; add to img.src # btoa(data)
document.querySelector("#hlogo img").src = "data:;base64,"+ data;
},
error:function (xhr, ajaxOptions, thrownError){
switch (xhr.status) {
case 400:
// Take action, referencing xhr.responseText as needed.
case 404:
// Take action, referencing xhr.responseText as needed.
case 500:
// Take action, referencing xhr.responseText as needed.
}
});
Notes
https://www.rfc-editor.org/rfc/rfc2397#section-3
dataurl := "data:" [ mediatype ] [ ";base64" ] "," data
mediatype := [ type "/" subtype ] *( ";" parameter )
data := *urlchar
parameter := attribute "=" value
https://www.rfc-editor.org/rfc/rfc2046#section-4.2
Using of a generic-purpose image viewing application this way
inherits the security problems of the most dangerous type supported
by the application.
https://www.rfc-editor.org/rfc/rfc2397#page-4
The effect of using long "data" URLs in applications is currently
unknown; some software packages may exhibit unreasonable behavior
when confronted with data that exceeds its allocated buffer size.
Other References
Unknown file type MIME?
Asynchronously load images with jQuery

Xdomain ajax html scrape is loading images when wrapping data respose in jquery

I'm trying to make a cross domain request to fetch the html, cache it and then iterate over the cached html to pull out data and eventually put it on the page. This is working but it wastes http reqs.
The problem is that once I wrap data.responseText with jquery $(data.responseText) it then goes and makes 40 http requests to pull in images.
Is it possible to just cache the a jquery html object inside of a variable without the extra image requests?
Using this x-domain hack here:
https://github.com/padolsey/jQuery-Plugins/blob/master/cross-domain-ajax/jquery.xdomainajax.js
getPage: (baseUrl) ->
console.log("beg scraping")
$.ajax
url: baseUrl,
type: "get",
dataType: "",
success: (data) =>
frag = data.responseText
#page = $(frag) # cache in object, now 40 extra reqs.
# this doesn't work, only returns images
##page = $(frag).find('[src]').remove()
console.log "Scraping done"
error: (status) ->
#window.pushError("getPage error: #{status}")
You can quickly search the text and remove all <img> elements. Then create the jQuery object:
var no_images = $(data.responseText.replace(/<img[^>]*>/g, ''));
Here's another thread you may find helpful:
load an HTML string into jQuery without requesting images
Alternatively, if you want to keep the images without automatically requesting them, you can replace the src attribute with something that wont automatically be fetched. e.g.
page.replace(/src/g, 'source');
This will keep the src reference under 'source' instead, and wont automatically load the image.

Adding a random number after the URL

I've got a site which uses jQuery and Ajax to change the site content without reloading the page. The site contains content which I often change. But somehow the page gets saved in the cache so it doesnt show the changes.
I tried several things to make the browser not to save the site into the cache like METAs and PHP. But it doesnt work.
I think it has to do with the fact, that the page always has the same URL so I thought about adding a random number to it like:
window.location.hash = $(this).attr('href').substr(0,$(this).attr('href').length-5);
(It's not my code, found it with some googlin) But this only adds the link ID I clicked on to the URL. I don't know where to put "Math.random()" to add a random number.
Hope you can help!
Just use cache : false. jQuery will automatically add a timestamp to the end of the URL for you, making sure that ajax requests are never cached.
Quoting the the API reference for .ajax()
cache
Default: true, false for dataType 'script' and 'jsonp'
If set to false, it will force requested pages not to be cached by the browser. Setting cache to false also appends a query string parameter, "_=[TIMESTAMP]", to the URL.
Examples
Globally disable caching for all future ajax requests. See .ajaxSetup()
$.ajaxSetup({
cache: false
});
Disable caching per request. See .ajax()
$.ajax({
url: "test.html",
cache: false,
success: function(html){
$("#results").append(html);
}
});
If you are using jQuery's AJAX functions, try setting $.ajaxSetup( { cache: false } ) at the top of your page, and let jQuery take care of it for you.
Like most mentionned, you should use the jQuery cache parameter, but for your information, it is often done not using Math.random but with new Date().valueOf(), which is a time value pretty much guaranteed to be unique.
window.location.hash = $(this).attr('href')
.substr(0,$(this).attr('href').length-5)
+ Math.random();
Best option is to use timestamp with the request:
window.location.hash = $(this).attr('href')
.substr(0,$(this).attr('href').length-5)
+ timestamp;

JQuery external Ajax call not working in IE

I have an ajax script that sends some data to an external URL. The external URL is hosted on the same server, however the domain is different than the source of the ajax call.
This is working perfectly in Firefox and Chrome. However in IE The ajax call does not go through, and the Return False function does not either work (once the ajax call fails).
Below is my code:
$.get('http://myexternaldomian.com/feedback/save.php', {
answer: $('#answer').val(),
page_url: pathname
});
// Keeps the user on the page
return false;
When I try removing the http:// from the ajax url, the return false does work.
Any help on this would be greatly appreciated. Thank You
From jQuery documentation
Due to browser security restrictions,
most "Ajax" requests are subject to
the same origin policy; the request
can not successfully retrieve data
from a different domain, subdomain, or
protocol.
and Same Origin Policy on Wiki
I'm surprised any of them are working. Browsers generally don't allow ajax calls to a domain other than the one the current page came from.
The main exception to this rule is if you make an ajax call using jsonp (json with padding). You can do this with jQuery, here's how. Look under the dataType option.
(this is copypaste from my another similar answer). You could try enabling "jQuery.support.cors=true" flag and see how it goes. I use jQuery v1.7.2.
I had to load webpage from local disk "file:///C:/test/htmlpage.html", call "http://localhost/getxml.php" url, and do this in IE8+ and Firefox12+ browsers, use jQuery v1.7.2 lib to minimize boilerplate code. After reading dozens of articles finally figured it out. Here is my summary.
server script (.php, .jsp, ...) must return http response header Access-Control-Allow-Origin: *
before using jQuery ajax set this flag in javascript: jQuery.support.cors = true;
you may set flag once or everytime before using jQuery ajax function
now I can read .xml document in IE and Firefox. Other browsers I did not test.
response document can be plain/text, xml, json or anything else
Here is an example jQuery ajax call with some debug sysouts.
jQuery.support.cors = true;
$.ajax({
url: "http://localhost/getxml.php",
data: { "id":"doc1", "rows":"100" },
type: "GET",
timeout: 30000,
dataType: "text", // "xml", "json"
success: function(data) {
// show text reply as-is (debug)
alert(data);
// show xml field values (debug)
//alert( $(data).find("title").text() );
// loop JSON array (debug)
//var str="";
//$.each(data.items, function(i,item) {
// str += item.title + "\n";
//});
//alert(str);
},
error: function(jqXHR, textStatus, ex) {
alert(textStatus + "," + ex + "," + jqXHR.responseText);
}
});
http://en.wikipedia.org/wiki/Same_origin_policy
I dont think it should work on Chrome or Firefox, unless you testing on localhost or something like that, this would be against the crossdomain policy.
What you need is to proxy it inside the same domain, use php to connect to the destination you need and call the url from the same domain.
save_cross_domain.php -> connect through server to the desired url
then ajax calls save_cross_domain.php
you should add a
callback=?
to your url and handle this on the server side.
I did this once for a java servlet, and when the callback param was included I added an extra pair of parenteses around the json response..
hope it helps!
A couple of things:
The answers/conversation for this question has gone a bit out of context. Actually from the question it was more implied how to make ajax calls in IE. [Atleast modify the question title, else the question is very localized]
A couple of solutions to this cross-domain issue:
CORS[compatible after IE7]
JSONP [ here actually the browser takes in the input thinking it is a script]
server side encoding

How do I stop jquery appending a unique id to scripts called via ajax?

I'm using jquery's ajax functions to grab a page fragment and display in a section of a page - this fragment includes html and references to external js files.
The program flow looks like this:
Main Page calls -> Fragment page which calls -> various large js files via script tags.
I've turned on the cache option on my initial ajax call so that the fragement page gets cached (no unique IDs appended to the url), however when the fragment is loaded, it appears that jquery rewrites the script urls to include a unix timestamp so that the browser downloads a new copy of the scripts every time. The scripts i'm calling are around 250kb minified and it's really hurting the user experience as the browser locks up whenever they're called. Is this a desired behaviour of jquery? Is there a way to disable the url rewrites?
Many many thanks for your help
This solution is less of a hack than Murdoch's solution:
$.ajaxPrefilter('script', function(options) {
options.cache = true;
});
See http://api.jquery.com/jQuery.ajaxPrefilter/
Looks like jQuerys's evalScript function is messing you up...
Line 543 of jQuery:
function evalScript( i, elem ) {
if ( elem.src )
jQuery.ajax({
url: elem.src,
async: false,
dataType: "script"
});
else
jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
if ( elem.parentNode )
elem.parentNode.removeChild( elem );
}
Here is the breakdown of what happens:
The Main Page's JS calls:
$.ajax({
url:"frag.htm",
type:"GET",
success:callBackFunction
})
and GETs frag.htm which contains something like this:
<html><head><script src="test.js"></script></head><body>Content</body></html>
then your callback function is called which probably looks like this:
function callBackFunction(data){
$("#ajaxContent").html(data); // <- this is the beginning of your problems...
}
When jQuery's html(data) function is called is "cleans" the HTML by removing any script tags and then calls evalScript on each one.
evalScript, as you can see, doesn't specify "cache:true" so when it goes through $.ajax cache is null. When cache is null and the dataType is "script" jQuery sets cache=false.
So, to circumvent this problem try this:
function callBackFunction(data){
var tempAJAX = $.ajax; // save the original $.ajax
$.ajax=function(s){ // wrap the old $.ajax so set cache to true...
s.cache=true;
tempAJAX(s); // call old $.ajax
}
$("#ajaxContent").html(data); // insert the HTML and download the <script>s
$.ajax = tempAJAX; // reset $.ajax to the original.
}
}
Before we insert the new HTML from "frag.htm" into the Main Page we intercept all calls to $.ajax, modify the object to include cache=true, and then after the script is loaded insert the HTML.
Let me know if you have any questions.
Force the webserver to serve the script with a expire date in the future.
If you use dataType = "script" as an option for jquery ajax the caching will be disabled by default, see http://docs.jquery.com/Ajax/jQuery.ajax#options, try set it manually to "html".
$.ajax({
type: "GET",
url: "test.js",
dataType: "html" // if not set jquery will guess what type it is and disables caching when matching "script"
});

Categories

Resources