Reputation: 546
I am working on an application that loads HTML content into a DIV tag using the jQuery $.ajax() function. The $.ajax function is run every few seconds to get updates. The HTML content (a PHP script) is rather large and I do not want to load it into the div unless the content has actually changed since the last load. I need to know when a 304 comes back and do nothing - as opposed to loading the HTML into the div from a cache.
I have tried setting:
ifModified: true
and this doesn't seem to return an error as expected.
This leaves me with two questions:
1) Does jQuery think the page is new every time because it's loading a dynamic page - even if the page has not changed since last load?
2) If no to question 1, then is it possible to make a jQuery $.ajax() call and have the error method execute when a 304 is returned?
Here is my test code - just to see if I can catch a 304:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>AJAX Conditional GET Request Test</title>
<script type="text/javascript" src="../jquery/jquery-2.1.4.min.js"></script>
</head>
<body>
<input type="submit" name="button" id="button" value="Check for updates" onclick="javascript:runUpdate();" />
<div id="status" style="width: 100px; height: 12px;"></div>
<script type="text/javascript">
function runUpdate()
{
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
var time = h+":"+m+":"+s;
$.ajax({
type: "GET",
url: "../dir/phpscriptthatsometimesupdates.php",
ifModified: true,
success: function(data){
$("#status").html("Updated "+time);
},
error: function(data, status, error){
$("#status").html("Not updated "+time);
}
});
}
</script>
</body>
</html>
Every time I run the test it says the file has been updated - even when it has not.
I have also tried using an "If-Modified-Since" using a future date with no success:
headers: {"If-Modified-Since": "Sun, 10 Apr 2016 00:00:00 GMT"}
Server is running:
Apache 2.2.15 (CentOS)
PHP 5.6.17
jQuery 2.1.4
Update:
I tried making a call to a PHP file the used:
header("Last-Modified: Fri, 08 Apr 2016 00:00:00 GMT");
to set the Last-Modified to a time in the past. I checked using my browser tools and saw that the Last-Modified was sent. 5 sequential calls from AJAX to this script did not display an error.
I also read through How to check if jQuery.ajax() request header Status is "304 Not Modified"? but what it describes seems to run contrary to the jQuery documentation explaining the ifModified argument which reads:
ifModified (default: false)
Type: Boolean
Allow the request to be successful only if the response has changed
since the last request. This is done by checking the Last-Modified
header. Default value is false, ignoring the header. In jQuery 1.4 this
technique also checks the 'etag' specified by the server to catch
unmodified data.
or am I missing something? According to the linked post I also tried:
headers: {"If-Modified-Since": "Fri, 08 Apr 2016 00:00:00 GMT"}
but was not successful.
Upvotes: 0
Views: 1831
Reputation: 546
From what I have found, it is not possible to catch the 304 directly as stated in How to check if jQuery.ajax() request header Status is "304 Not Modified"?, but it is still possible to do an internal comparison of xhr.getResponseHeader("Last-Modified") as retrieved by a HEAD request with a stored value before loading content. While this solution does not specifically look at the 304, it does allow a script to decide whether to load content based on it's Last-Modified time instead of loading cached content continuously and wasting resources.
The basis of this idea came from this excellent write-up I found here: http://www.raymondcamden.com/2012/04/05/Using-jQuery-to-conditionally-load-requests/
Which can also be found here: https://gist.github.com/cfjedimaster/2313466
However, when I tried the example code in this write-up I came across the problem of my browser caching the HEAD response and always trying to load old content, even when the file had been updated. In order to make the example work, I added cache:false to the $.ajax() HEAD request call.
As pointed out by @cmorrissey the PHP script we are checking for updates MUST send a Last-Modified header as such:
header("Last-Modified: Mon, 11 Apr 2016 00:00:00 GMT");
In order to know if the content of the PHP script has changed or not, we can set the Last-Modified via header() using the Last-Modified time of a file the PHP script is loading to generate content. This way, we will always know if the PHP script will have new content. This time can be grabbed using either filemtime() if we are loading the file from disk, or getting the Last-Modified header from the file if we are loading remotely.
Below is a full, working example minus the PHP script we would be checking for updates (somefile.php) and the JSON or text file it would be checking for updates.
<!DOCTYPE html>
<html>
<head>
<title>AJAX Conditional GET Request Test</title>
<script type="text/javascript" src="jquery-2.1.4.min.js"></script>
</head>
<body>
<input type="submit" name="button" id="button" value="Check for updates" onclick="javascript:runUpdate();" />
<div id="status" style="width: 300px; height: 12px;"></div>
<script type="text/javascript">
var resourceLastTime = "";
function runUpdate()
{
var today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
var time = h+":"+m+":"+s;
var resourceUrl = "somefile.php";
if(resourceLastTime != "")
{
$.ajax({
type:"HEAD",
url: resourceUrl,
cache: false,
success: function(res,code,xhr){
if(resourceLastTime != xhr.getResponseHeader("Last-Modified"))
{
getUrl(resourceUrl);
$("#status").html("Updated "+time);
}
else
{
$("#status").html("Not updated "+time);
}
},
error: function(data, status, error){
$("#status").html(error+" "+status+" "+time);
}
});
}
else
{
getUrl(resourceUrl);
$("#status").html("First load "+time);
}
}
function getUrl(urlToGet)
{
var urlContents = "";
$.ajax({
url:urlToGet,
type:"get",
cache:false,
success:function(res,code,xhr) {
resourceLastTime = xhr.getResponseHeader("Last-Modified");
//must process res here due to asynchronous nature of $.ajax() function
}
});
}
</script>
</body>
</html>
Upvotes: 1
Reputation: 511
How to check if jQuery.ajax() request header Status is "304 Not Modified"?
jquery will handle a 304 response as it would be a 200 response and therfore your error function will never be called.
Upvotes: 0