按下后退按钮时 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 请求,当dataTypescriptjsonp 时自动设置【参考方案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 响应的主要内容,如果未能解决你的问题,请参考以下文章

当我按下返回按钮时应用程序没有响应

如何阻止 chrome 缓存

按下后退按钮时避免启动屏幕活动

servlet会话,注销后,按下浏览器的后退按钮时,再次显示安全页面[重复]

用于控制 ajax 负载的后退和前进按钮

在iOS中按下后退按钮时如何创建确认弹出窗口?