按下后退按钮时,Chrome会显示ajax响应

时间:2012-03-31 13:22:56

标签: ajax google-chrome back-button

我遇到了一个问题,如果我使用jQuery的Get方法来获取一些内容,如果我点击回来,而不是实际返回历史记录中的一个页面,它会显示Ajax查询返回的内容。

有什么想法吗?

http://www.dameallans.co.uk/preview/allanian-society/news/56/Allanian-test

在上面的页面中,如果您在更改页面后单击后面时会注意到注释列表下方的分页,则会显示用于生成注释列表的HTML内容。

我注意到它并不总是这样做,但是如果您点击不同的页面几次并单击后退按钮,它只会在窗口中显示json文本而不是网站。

出于某种原因,这只会影响Chrome,因为IE和Firefox可以正常工作。

9 个答案:

答案 0 :(得分:44)

确保您的AJAX请求使用完整HTML文档中的其他URL。 Chrome会缓存最近的请求,即使它只是部分请求。

https://code.google.com/p/chromium/issues/detail?id=108425

答案 1 :(得分:18)

如果您使用jQuery和History API(或某些库如history.js),您应该将$ .getJSON更改为$ .ajax,并将缓存设置为false:

$.ajax({
    dataType: "json",
    url: url,
    cache: false,
    success: function (json) {...}
});

答案 2 :(得分:14)

实际上,这是根据规范而不是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');
});

答案 3 :(得分:5)

您还可以在ajax网址的末尾添加随机值。这将忽略之前的chrome缓存并将请求新版本

url = '/?'+Math.random()

答案 4 :(得分:2)

只需将以下标题添加到响应标题:

Vary: Accept

答案 5 :(得分:1)

我无法为每个ajax请求提供不同的URL,因为它是一个ajax分页,声明标头上没有缓存没有做任何事情,所以我只在标题是针对ajax请求时在视图中包含一些javascript:

<script>
if (typeof jQuery == 'undefined') {
    window.location = "<?php echo $this->here; ?>";
}
</script>

这是一个肮脏的技巧,但它的工作原理,如果ajax内容正常加载,容器已加载Jquery,所以它什么都不做。但是如果加载没有周围内容的ajax假设内容,Jquery就会丢失(至少在我的情况下),所以我重定向到当前页面,请求包含所有头文件和脚本的普通GET页面。

如果你把它放在页面的顶部,用户就不会注意到,因为它不会等到页面加载,一旦浏览器获得这4行就会重定向......

替换在这里; ?&GT;通过你APP中的当前网址,这是一个CakePhp 2.X

答案 6 :(得分:1)

在 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://stackoverflow.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');

答案 7 :(得分:0)

@ 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

答案 8 :(得分:0)

如果我想使用laravel控制器的索引方法返回html和json响应,则在端点的末尾添加一个get参数以传递浏览器缓存:

axios.get(url, {params: {ajax: 1}})