按下后退按钮时 Chrome 显示 ajax 响应
Posted
技术标签:
【中文标题】按下后退按钮时 Chrome 显示 ajax 响应【英文标题】:Chrome displays ajax response when pressing back button 【发布时间】:2012-04-14 22:08:28 【问题描述】:我遇到了一个问题,如果我使用 jQuery 的 Get 方法来获取一些内容,如果我单击返回,而不是实际返回历史中的一页,而是显示 Ajax 查询返回的内容。
有什么想法吗?
http://www.dameallans.co.uk/preview/allanian-society/news/56/Allanian-test
在上面的页面中,如果您使用 cmets 列表下方的分页,您会在更改页面后单击返回时注意到,它显示了用于生成 cmets 列表的 html 内容。
我注意到它并不总是这样做,但是如果您在不同的页面上单击几次并单击后退按钮,它只会在窗口而不是网站中显示 json 文本。
由于某种原因,这只会影响 Chrome,因为 IE 和 Firefox 工作正常。
【问题讨论】:
您找到解决此问题的方法了吗?我也遇到了同样的问题。 【参考方案1】:确保您的 AJAX 请求使用与完整 HTML 文档不同的 URL。 Chrome 会缓存最近的请求,即使它只是部分请求。
https://code.google.com/p/chromium/issues/detail?id=108425
【讨论】:
我已经被这个虫子拔掉了好几个星期。谢谢! 快速解决方案:在 ajax 请求中将“?ajax=true”附加到您的 url。 答案实际上应该是“确保 URL 未被缓存”,其中一种解决方案可能使用不同的 URL... 我不太明白这个问题。一方面是因为缓存,另一方面它不使用缓存。如果是这样,它不会产生新的响应。我的应用程序对 Ajax 显示不同的响应,对非 ajax 和背面显示不同的响应,Chrome 显示这个 Ajax 响应。这意味着它不使用缓存。太可笑了,怎么连Ajax都缓存起来了?【参考方案2】:如果您使用带有 History API(或类似 history.js 的库)的 jQuery,您应该将 $.getJSON 更改为 $.ajax,并将缓存设置为 false:
$.ajax(
dataType: "json",
url: url,
cache: false,
success: function (json) ...
);
【讨论】:
cache: false
选项通过将时间戳附加到 URL 来工作,因此如果您使用 jQuery,它是最佳解决方案。仅适用于 HEAD 和 GET 请求,当dataType
为script
或jsonp
时自动设置【参考方案3】:
实际上,这是根据规范缓存系统的预期行为,而不是 chrome 问题。缓存仅根据 URL 和请求方法(get、post、...)区分请求,而不是任何请求标头。
但是有一个 Vary 标头告诉浏览器在检查缓存时考虑一些标头。例如,通过将 Vary:X-Requested-With 添加到服务器响应中,浏览器知道如果请求 X-Requested-With 标头更改,则此响应会发生变化。或者通过将 Vary:Content-Type 添加到服务器响应中,浏览器知道如果请求 Content-Type 标头更改,则此响应会发生变化。
您可以将此行添加到您的 php 路由器:
header('Vary:X-Requested-With');
并在 node.js 中使用中间件:
app.use(function(req, res)
res.header('Vary', 'X-Requested-With');
);
【讨论】:
为我工作。我必须为 ajax 和来自 url 栏的经典收入提供相同的 url。我使用的 Ajax 库没有 cache=false.... 这实际上是最优雅的答案。谢谢!【参考方案4】:您还可以在 ajax url 的末尾添加一个随机值。这将忽略以前的 chrome 缓存并请求新版本
url = '/?'+Math.random()
【讨论】:
【参考方案5】:只需将以下标头添加到 Response 标头:
Vary: Accept
【讨论】:
【参考方案6】:我不能为每个 ajax 请求提供不同的 url,因为它是一个 ajax 分页,声明标题上没有缓存什么也没做,所以我只在标题用于 ajax 请求时在视图中包含了一些 javascript:
<script>
if (typeof jQuery == 'undefined')
window.location = "<?php echo $this->here; ?>";
</script>
这是一个肮脏的把戏,但它确实有效,如果正常加载 ajax 内容,则容器已加载 Jquery,因此它什么也不做。但是,如果您在没有周围内容的情况下加载 ajax 假定内容,则缺少 Jquery(至少在我的情况下),所以我重定向到当前页面,请求包含所有标题和脚本的正常 GET 页面。
如果你把它放在页面顶部,用户不会注意到,因为它不会等到页面加载,一旦浏览器得到这 4 行,它就会重定向......
这里替换; ?> 通过你APP中的当前url,这是一个CakePhp 2.X
【讨论】:
【参考方案7】:在 2021 年的 Chrome 中仍然存在这个问题。
问题是对与用户当前所在的 URL 相同的 URL 进行底层 ajax 请求。 我在 Symfony 工作,为我完成工作的完整修复是
$response->headers->addCacheControlDirective('no-cache', true);
$response->headers->addCacheControlDirective('max-age', 0);
$response->headers->addCacheControlDirective('s-maxage', 0);
$response->headers->addCacheControlDirective('must-revalidate', true);
$response->headers->addCacheControlDirective('no-store', true);
/**
* from https://***.com/a/1975677/5418514
*
* The HTTP request header 'Accept' defines the Content-Types a client can process.
* If you have two copies of the same content at the same URL, differing only in Content-Type,
* then using Vary: Accept could be appropriate.
*/
$response->headers->set('Vary', 'Accept');
【讨论】:
【参考方案8】:@abraham 的回答是正确的。
我只是想为 Rails 发布一个解决方案:您只需添加不同的路径到 routes.rb
。
例如,我有resource :people
,我想从 ajax 部分组成索引页面,其中之一是人员列表。直接的方法是创建index.js.erb
并使用url: people_path
通过ajax 加载部分。但是这里出现了问题。
所以,对于 Rails,它只需要添加一条不同的路线,比如
get 'people_list', to: 'people#index', as: :people_list, format: :js
【讨论】:
【参考方案9】:如果我想使用 laravel 控制器的 index 方法返回 html 和 json 响应,我在端点末尾添加一个 get 参数以传递浏览器缓存:
axios.get(url, params: ajax: 1)
【讨论】:
以上是关于按下后退按钮时 Chrome 显示 ajax 响应的主要内容,如果未能解决你的问题,请参考以下文章