0

I have some JavaScript that sends an XMLHttpRequest() to a PHP file every minute to fetch some JSON data, and then display it.

The first time this runs, after 1 minute, I get the "Success!" in the browser Console, and a request was made to /data.php in the Network tab.

But subsequent times, I get "Success!", but with the same data (including the same time), and the Network tab shows no further requests were made to /data.php

const url = "/data.php";

setInterval(refreshData, 60000);

var refreshData = function () {
  var xhr = new XMLHttpRequest();

  xhr.onreadystatechange = function () {
    // Only run if the request is complete
    if (xhr.readyState !== 4) return

    if (xhr.status >= 200 && xhr.status < 300) {
      console.log("Success!", xhr);
      displayData(JSON.parse(xhr["responseText"]));
    } else {
      console.error("Error fetching data");
    }
  };

  xhr.open("GET", url);
  xhr.send();
};

Here's data.php:

header('Content-type: application/json;charset=utf-8');
$data = array(
    "foo" => "bar",
    "time" => time(),
);
echo json_encode($data);

I can solve this by adding a cache-busting "?" + new Date().getTime() to the url called by the JS.

Or by doing this in the PHP:

header('Cache-Control: no-cache, no-store, must-revalidate');
header('Pragma: no-cache');
header('Expires: 0');

So I could use one of those solutions, but they smell a bit bad. I've tried this:

$seconds_to_cache = 1;
header("Cache-Control: max-age=$seconds_to_cache");
header("Pragma: cache");
$expire_time = gmdate("D, d M Y H:i:s", time() + $seconds_to_cache) . " GMT";
header("Expires: $expire_time");

but it doesn't have any effect. What am I missing?

Phil Gyford
  • 12,283
  • 12
  • 64
  • 130
  • you can add cache control into the xhr request - https://stackoverflow.com/a/48969579/1772933 – Kinglish Jun 16 '21 at 11:51
  • 1
    Hello, before answering to the hole question, there is something that i did not understand when you said `and the Network tab shows no request was actually made to /data.php` , instead i tried your JS code (without data.php) and i decreased the setIntervalTime to `500` , so that the requests are executed normally without any problem.. so i want to know, what if you test your JS with another php file ? – sohaieb azaiez Jun 16 '21 at 11:55
  • @Kinglish Thanks. I've just tried adding `xhr.setRequestHeader("Cache-Control", "no-cache, no-store, max-age=0");`, and then the "Expires" and "Pragma" headers too, but with no effect unfortunately. – Phil Gyford Jun 16 '21 at 13:04
  • @sohaiebazaiez Thanks for trying! I'm not sure what the purpose is of trying with a different PHP file. Why would that be different? And I clarified that sentence in my question - the Network tab only shows the first request to `data.php`. – Phil Gyford Jun 16 '21 at 13:05
  • If you load data.php in a browser window and hit soft reload does it update correctly? – James Jun 16 '21 at 13:07
  • @James Yes it does - I can refresh it every second and the "time" value increases. – Phil Gyford Jun 16 '21 at 13:13
  • "I can solve this by adding a cache-busting "?" + new Date().getTime() to the url called by the JS." - this is pretty standard, I don't see why it "smells bad"... – Joe Jun 16 '21 at 13:13
  • @Joe I may end up doing this. I just felt that the question of whether to cache, and how long for, should maybe be done by the server, ideally. – Phil Gyford Jun 16 '21 at 13:23
  • I'd say take a look at all the headers on the response from the server (to the request to `/data.php`) to see whether any other cache affecting headers are added by the hosting server software. – msbit Jun 17 '21 at 02:01

0 Answers0