113

with fetch('somefile.json'), it is possible to request that the file be fetched from the server and not from the browser cache?

in other words, with fetch(), is it possible to circumvent the browser's cache?

sideshowbarker
  • 72,859
  • 23
  • 167
  • 174
cc young
  • 17,173
  • 30
  • 86
  • 144
  • 1
    Do you have a reference for *fetch* in the [*ECMA-262 ed 6 draft*](https://people.mozilla.org/~jorendorff/es6-draft.html)? I don't see it. Or do you mean the [*WHATWG Fetch living standard*](https://fetch.spec.whatwg.org)? – RobG Mar 25 '15 at 02:46
  • RobG - using https://developer.mozilla.org/en-US/docs/Web/API/FetchEvent – cc young Mar 25 '15 at 03:29

4 Answers4

137

Fetch can take an init object containing many custom settings that you might want to apply to the request, this includes an option called "headers".

The "headers" option takes a Header object. This object allows you to configure the headers you want to add to your request.

By adding pragma: no-cache and a cache-control: no-cache to your header you will force the browser to check the server to see if the file is different from the file it already has in the cache. You could also use cache-control: no-store as it simply disallows the browser and all intermediate caches to store any version of the returned response.

Here is a sample code:

var myImage = document.querySelector('img');

var myHeaders = new Headers();
myHeaders.append('pragma', 'no-cache');
myHeaders.append('cache-control', 'no-cache');

var myInit = {
  method: 'GET',
  headers: myHeaders,
};

var myRequest = new Request('myImage.jpg');

fetch(myRequest, myInit)
  .then(function(response) {
    return response.blob();
  })
  .then(function(response) {
    var objectURL = URL.createObjectURL(response);
    myImage.src = objectURL;
  });
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ES6</title>
</head>
<body>
    <img src="">
</body>
</html>

Hope this helps.

burningfuses
  • 1,629
  • 1
  • 10
  • 11
  • 6
    What about using `new Request` and passing some argument to the `cache` options? I am trying to use that, but it does not work. – Mitar Jan 21 '16 at 07:05
  • 1
    Does the capitalization of the headers matter? I.e. "Cache-Control" vs "cache-control". – Isaac Lyman Aug 29 '18 at 20:29
  • 4
    @IsaacLyman, although HTTP headers are case-insensitive, I suggest you follow the proposed documentation, which is: "Cache-Control". Reference: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers – burningfuses Aug 30 '18 at 00:26
135

Easier use of cache modes:

  // Download a resource with cache busting, to bypass the cache
  // completely.
  fetch("some.json", {cache: "no-store"})
    .then(function(response) { /* consume the response */ });

  // Download a resource with cache busting, but update the HTTP
  // cache with the downloaded resource.
  fetch("some.json", {cache: "reload"})
    .then(function(response) { /* consume the response */ });

  // Download a resource with cache busting when dealing with a
  // properly configured server that will send the correct ETag
  // and Date headers and properly handle If-Modified-Since and
  // If-None-Match request headers, therefore we can rely on the
  // validation to guarantee a fresh response.
  fetch("some.json", {cache: "no-cache"})
    .then(function(response) { /* consume the response */ });

  // Download a resource with economics in mind!  Prefer a cached
  // albeit stale response to conserve as much bandwidth as possible.
  fetch("some.json", {cache: "force-cache"})
    .then(function(response) { /* consume the response */ });

refrence:https://hacks.mozilla.org/2016/03/referrer-and-cache-control-apis-for-fetch/

MJ Vakili
  • 2,228
  • 1
  • 18
  • 24
  • 1
    This is a more appropriate answer. You can handle headers like 'If-Modified-Since' and 'If-None-Match' by these options. – Nigiri Mar 15 '17 at 07:57
  • 10
    This seems to work in Firefox (54) but not Chrome (60). burningfuses's answer does work. – Scimonster Aug 15 '17 at 12:10
  • 1
    I have tested it, and as for today (November 2019) this method seems to be working on Opera, Chrome and FireFox on both Windows, Linux and Android. The burningfuses method fails at least on Opera. – Sopalajo de Arrierez Nov 27 '19 at 15:09
  • In my case it did not force cache reload until I additionally specified `pragma: no-cache` – Klesun Dec 30 '19 at 13:40
  • 1
    This respects CORS unlike the winning answer. – skrat Dec 15 '20 at 02:55
  • Yes the accepted answer does not work if CORS blocks the various headers or if the server does not support CORS at all. – Frank Weindel Dec 13 '21 at 20:55
19

You can set 'Cache-Control': 'no-cache' in the header like this::

return fetch(url, {
  headers: {
    'Cache-Control': 'no-cache'
  }
}).then(function (res) {
  return res.json();
}).catch(function(error) {
  console.warn('Failed: ', error);
});
Agu Dondo
  • 11,290
  • 7
  • 52
  • 65
18

None of the solutions seemed to work well for me, but this relatively clean (AFAICT) hack did work (adapted from https://webmasters.stackexchange.com/questions/93594/prevent-browser-from-caching-text-file):

  const URL = "http://example.com";
  const ms = Date.now();
  const data = await fetch(URL+"?dummy="+ms)
    .catch(er => game_log(er.message))
    .then(response => response.text());

This is just adding a dummy parameter that changes on every call to a query. By all means, if other solutions appear to work, I suggest using those, but in my tests, they did not work in my case (e.g. those using Cache-Control and pragram).

bbarker
  • 9,715
  • 7
  • 34
  • 54