fetch(),如何发出非缓存请求?

Posted

技术标签:

【中文标题】fetch(),如何发出非缓存请求?【英文标题】:fetch(), how do you make a non-cached request? 【发布时间】:2015-05-28 13:54:32 【问题描述】:

使用fetch('somefile.json'),是否可以请求从服务器而不是从浏览器缓存中获取文件?

也就是说,用fetch(),是否可以绕过浏览器的缓存?

【问题讨论】:

ECMA-262 ed 6 draft 中有 fetch 的参考吗?我没看到。还是您的意思是WHATWG Fetch living standard RobG - 使用developer.mozilla.org/en-US/docs/Web/API/FetchEvent 【参考方案1】:

Fetch 可以采用包含许多您可能希望应用于请求的自定义设置的 init 对象,其中包括一个名为“headers”的选项。

“headers”选项采用Header 对象。此对象允许您配置要添加到请求中的标头。

通过将 pragma: no-cachecache-control: no-cache 添加到您的标题中,您将强制浏览器检查服务器以查看文件是否不同于它已经在缓存中的文件。您还可以使用 cache-control: no-store,因为它只是禁止浏览器和所有中间缓存存储返回响应的任何版本。

这是一个示例代码:

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>

希望这会有所帮助。

【讨论】:

如何使用new Request 并将一些参数传递给cache 选项?我正在尝试使用它,但它不起作用。 标题的大小写重要吗? IE。 “缓存控制”与“缓存控制”。 @IsaacLyman,虽然 HTTP 标头不区分大小写,但我建议您遵循建议的文档,即:“Cache-Control”。参考:developer.mozilla.org/en-US/docs/Web/HTTP/Headers【参考方案2】:

更容易使用缓存模式:

  // 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 */ );

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

【讨论】:

这是一个更合适的答案。您可以通过这些选项处理“If-Modified-Since”和“If-None-Match”等标题。 这似乎适用于 Firefox (54) 但不适用于 Chrome (60)。 Burningfuses 的回答确实有效。 我已经测试过了,就今天(2019 年 11 月)而言,这种方法似乎在 Windows、Linux 和 android 上的 Opera、Chrome 和 FireFox 上都有效。 Burningfuses 方法至少在 Opera 上失败了。 在我的情况下,它不会强制缓存重新加载,直到我另外指定 pragma: no-cache 这尊重 CORS,不像获胜的答案。【参考方案3】:

您可以像这样在标题中设置'Cache-Control': 'no-cache'::

return fetch(url, 
  headers: 
    'Cache-Control': 'no-cache'
  
).then(function (res) 
  return res.json();
).catch(function(error) 
  console.warn('Failed: ', error);
);

【讨论】:

【参考方案4】:

似乎没有一个解决方案对我很有效,但是这个相对干净的 (AFAICT) hack 确实有效(改编自 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());

这只是添加一个在每次调用查询时都会更改的虚拟参数。无论如何,如果其他解决方案似乎可行,我建议使用这些解决方案,但在我的测试中,它们在我的情况下不起作用(例如,那些使用 Cache-Controlpragram 的解决方案)。

【讨论】:

谢谢!这是唯一对我有用的东西。

以上是关于fetch(),如何发出非缓存请求?的主要内容,如果未能解决你的问题,请参考以下文章

服务器如何检测使用 fetch API 发出的请求?

如何在本地使用 fetch 从客户端向服务器发出请求而不会得到不透明的响应?

如何从 fetch javascript 请求的响应中获取数据

如何检查是不是向缓存发出请求?

Firefox fetch API:如何在请求中省略“origin”标头?

如何强制 window.location 发出 HTTP 请求而不是使用缓存?