Chrome отображает ответ Ajax при нажатии кнопки назад - PullRequest
50 голосов
/ 31 марта 2012

Я столкнулся с проблемой, заключающейся в том, что если я использую метод Get jQuery для получения некоторого контента, если я щелкаю назад, вместо того, чтобы фактически возвращаться на одну страницу в истории, он вместо этого отображает контент, возвращенный запросом Ajax.

Есть идеи?

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

На приведенной выше странице, если вы используете нумерацию страниц под списком комментариев, которую вы заметите при повторном нажатии после изменения страницы, будет показано содержимое HTML, использованное для создания списка комментариев.

Я заметил, что это не всегда происходит, но если вы щелкнете по другой странице несколько раз и нажмете кнопку "Назад", она просто отобразит текст json в окне вместо веб-сайта.

По какой-то причине это влияет только на Chrome, поскольку IE и Firefox работают нормально.

Ответы [ 7 ]

45 голосов
/ 12 апреля 2012

Убедитесь, что ваши запросы AJAX используют URL-адрес, отличный от полного HTML-документов. Chrome кэширует самый последний запрос, даже если он является частичным.

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

19 голосов
/ 10 августа 2014

На всякий случай, если вы используете jQuery с History API (или какой-либо библиотекой, например history.js), вы должны изменить $ .getJSON на $ .ajax с кэшем, установленным в false:

$.ajax({
    dataType: "json",
    url: url,
    cache: false,
    success: function (json) {...}
});
14 голосов
/ 20 февраля 2016

На самом деле это ожидаемое поведение системы кэширования в соответствии со спецификациями, а не проблема хрома. Кеш различает запросы только по 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');
});
5 голосов
/ 15 января 2015

Вы также можете добавить случайное значение в конец URL-адреса ajax. Это будет игнорировать предыдущий кэш Chrome и запросит новую версию

url = '/?'+Math.random()
2 голосов
/ 14 декабря 2017

Просто добавьте следующий заголовок к заголовкам Response :

Vary: Accept
1 голос
/ 15 ноября 2013

Я не мог дать разные URL-адреса для каждого запроса AJAX, так как это было разбиение по страницам на AJAX, так как объявление о том, что кеш заголовков не работает, ничего не дало, поэтому я включил небольшой JavaScript в представление, только когда заголовки были для запроса AJAX:

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

Это подвох, но он работает, если содержимое ajax нормально загружено, в контейнер загружен Jquery, поэтому он ничего не делает. Но если вы загружаете предполагаемый контент ajax без окружающего контента, Jquery отсутствует (по крайней мере, в моем случае), поэтому я перенаправляю на текущую страницу, запрашивая нормальную страницу GET со всеми заголовками и сценариями.

Если вы поместите его в верхнюю часть страницы, пользователь не заметит, потому что он не будет ждать загрузки страницы, он будет перенаправлен, как только браузер получит эти 4 строки ...

Заменить здесь; ?> по текущему URL в вашем приложении это был CakePhp 2.X

0 голосов
/ 28 ноября 2016

Ответ @ abraham правильный. Я просто хотел опубликовать решение для Rails: все, что вам нужно, это просто добавить другой путь к routes.rb.

Например, у меня есть resource :people, и я хочу составить индексную страницу из частей AJAX, одним из которых является список людей. Простой способ - создать index.js.erb и загрузить частичное с помощью ajax, используя url: people_path. Но здесь возникает проблема.

Итак, для Rails нужно просто добавить другой маршрут, например

get 'people_list', to: 'people#index', as: :people_list, format: :js

...