Is it possible to get the modified timestamp of a file using just JavaScript?
I use a JSON file to fill a page by javascript and I would like to show the timestamp o
You can do it if you're retrieving the file through true ajax (that is, through XMLHttpRequest
), provided you configure your server to send the Last-Modified
header when sending the data.
The fundamental thing here is that when you use XMLHttpRequest
, you can access the response headers. So if the server sends back Last-Modified
, you can use it:
var xhr = $.ajax({
url: "data.json",
success: function(response) {
display("Data is " + response.data + ", last modified: " + xhr.getResponseHeader("Last-Modified"));
}
});
Just tried that on Chrome, Firefox, IE8, and IE11. Worked well (even when the data was coming from cache).
You've said below that you need to do this in a loop, but you keep seeing the last value of the variable. That tells me you've done something like this:
// **WRONG**
var list = /*...some list of URLs...*/;
var index;
for (index = 0; index < list.length; ++index) {
var xhr = $.ajax({
url: list[index],
success: function(response) {
display("Data is " + response.data + ", last modified: " + xhr.getResponseHeader("Last-Modified"));
}
});
}
The problem there is that all of the success
callbacks have an enduring reference to the xhr
variable, and there is only one of them. So all the callbacks see the last value assigned to xhr
.
This is the classic closure problem. Here's one solution:
var list = /*...some list of URLs...*/;
list.forEach(function(url) {
var xhr = $.ajax({
url: url,
success: function(response) {
display("Data for " + url + " is " + response.data + ", last modified: " + xhr.getResponseHeader("Last-Modified"));
}
});
});
Since each iteration of the forEach
callback gets its own xhr
variable, there's no cross-talk. (You'll need to shim forEach
on old browsers.)
You said below:
I already thought about a closure problem, thats why I used an array
xhr[e]
in my loop overe
... But your example doesent help...
and linked to this code in a gist:
//loop over e....
nodename=arr[e];
node_json=path_to_node_json+nodename;
html +='<a href="'+node_json+'" target="_blank" id="host_'+nodename+'">data</a></td>'
+'</tr>';
xhr[e] = $.ajax({
url: node_json,
success: function(response) {
$('#host_'+nodename).append("last modified: " + xhr[e].getResponseHeader("Last-Modified"));
}
});
That still has the classic error: Your success
function closes over the variable e
, not the value it had when the success
function was created, and so by the time the success
function runs, e
has the last value assigned to it in the loop.
The forEach
example I gave earlier fits this perfectly:
// (I assume `node_json`, `html`, and `path_to_node_json` are all declared
// here, outside the function.)
arr.forEach(function(nodename) {
var xhr; // <=== Local variable in this specific call to the iteration
// function, value isn't changed by subsequent iterations
node_json=path_to_node_json+nodename;
html +='<a href="'+node_json+'" target="_blank" id="host_'+nodename+'">data</a></td>'
+'</tr>';
xhr = $.ajax({
url: node_json,
success: function(response) {
// Note: You haven't used it here, but just to emphasize: If
// you used `node_json` here, it would have its value as of
// the *end* of the loop, because it's not local to this
// function. But `xhr` is local, and so it isn't changed on
// subsequent iterations.
$('#host_'+nodename).append("last modified: " + xhr.getResponseHeader("Last-Modified"));
}
});
});