Safari на iOS 6 кеширует результаты $ .ajax?

1072

После обновления до iOS 6 мы видим, что веб-представление Safari берет на себя кеширование $.ajaxвызовов. Это в контексте приложения PhoneGap, поэтому оно использует Safari WebView. Наши $.ajaxвызовы являются POSTметодами, и мы установили в кэш значение false {cache:false}, но все же это происходит. Мы попытались вручную добавить TimeStampк заголовкам, но это не помогло.

Мы провели дополнительные исследования и обнаружили, что Safari возвращает кэшированные результаты только для веб-служб, которые имеют статическую сигнатуру функции и не меняются от вызова к вызову. Например, представьте себе функцию, которая называется что-то вроде:

getNewRecordID(intRecordType)

Эта функция снова и снова получает одни и те же входные параметры, но возвращаемые данные должны каждый раз отличаться.

Должно быть, в спешке Apple, чтобы сделать iOS 6 впечатляющим, они были слишком довольны настройками кэша. Кто-нибудь еще видел такое поведение на iOS 6? Если так, что именно вызывает это?


Обходной путь, который мы нашли, состоял в том, чтобы изменить сигнатуру функции так:

getNewRecordID(intRecordType, strTimestamp)

а затем всегда также передавайте TimeStampпараметр и просто отбрасывайте это значение на стороне сервера. Это работает вокруг проблемы. Я надеюсь, что это поможет какой-то другой бедной душе, которая потратит на это 15 часов, как я!

user1684978
источник
190
Это абсолютно шокирует. Мы также просто потратили пару часов, пытаясь понять, что что-то перестало работать. Наш логин AJAX, который выполняет POST (и имеет заголовки для предотвращения кеширования), кэшируется Safari, поэтому он просто возвращает тот же JSON, который он делал в прошлый раз, даже не пытаясь использовать сервер ... невероятно! Нам придется взломать исправление, но вы никогда не должны кэшировать POST, это безумие.
Киран
16
Опубликуйте свое решение как ответ, а не как обновление вопроса.
ChrisF
50
POST-запросы не идемпотентны, что означает, что они не должны кэшироваться, если ответ не рекомендует делать это через свои заголовки ответа.
Джеймс М. Грин
6
Чтобы Apple исправила это, отправьте сообщение об ошибке на bugreport.apple.com . Я сделал то же самое.
Матиас Биненс
11
Марк Ноттингем (председатель рабочей группы IETF HTTPbis) написал интересную запись в блоге об этом сегодня: mnot.net/blog/2012/09/24/caching_POST
Бенджамин

Ответы:

447

После небольшого исследования выясняется, что Safari на iOS6 будет кэшировать POST, которые не имеют заголовков Cache-Control или даже "Cache-Control: max-age = 0".

Единственный способ предотвратить кэширование на глобальном уровне вместо того, чтобы взламывать случайные строки запросов в конце вызовов службы, - установить «Cache-Control: no-cache».

Так:

  • Нет заголовков Cache-Control или Expires = iOS6 Safari будет кешировать
  • Cache-Control max-age = 0 и немедленное Expires = iOS6 Safari будет кешировать
  • Cache-Control: no-cache = iOS6 Safari НЕ будет кешировать

Я подозреваю, что Apple использует это из спецификации HTTP в разделе 9.5 о POST:

Ответы на этот метод не могут быть кэшированы, если ответ не включает в себя соответствующие поля заголовка Cache-Control или Expires. Однако ответ 303 (см. «Другое») можно использовать для того, чтобы указать пользовательскому агенту извлечь кэшируемый ресурс.

Так что в теории вы можете кэшировать POST-ответы ... кто знал. Но никто другой производитель браузеров никогда не думал, что это будет хорошей идеей до сих пор. Но это НЕ учитывает кэширование, когда не установлены заголовки Cache-Control или Expires, только когда они есть. Так что это должно быть ошибка.

Ниже приведено то, что я использую в правильной части конфигурации Apache для целевого использования всего моего API, потому что в действительности я не хочу ничего кешировать, даже получать. То, что я не знаю, как установить это только для POST.

Header set Cache-Control "no-cache"

Обновление: только что заметил, что я не указал, что это только когда POST одинаков, поэтому измените любые данные или URL POST, и все в порядке. Таким образом, вы можете, как упоминалось в другом месте, просто добавить некоторые случайные данные в URL или немного данных POST.

Обновление: вы можете ограничить «no-cache» только POST, если вы хотите, чтобы это было в Apache:

SetEnvIf Request_Method "POST" IS_POST
Header set Cache-Control "no-cache" env=IS_POST
Киран
источник
7
Я вижу, к чему идет Apple, но мы видим кэшированные ответы на POST-запросы, даже если наши ответы не содержат заголовков Cache-Control или Expires. Разве этот экземпляр iOS6 не должен кэшировать и отправлять каждый запрос. Этого не происходит.
Kango_V
138
Часть спецификации HTTP, которую вы цитировали, не оправдывает поведение кэширования iOS 6. Поведение по умолчанию должно заключаться в том, чтобы не кэшировать ответы POST (т. Е. Когда заголовок «Cache-Control» не определен). Поведение нарушает спецификацию и должно рассматриваться как ошибка. Любой, кто создает веб-сервисы xml / json api, должен украсить свои ответы POST "Cache-control: no-cache", чтобы обойти эту проблему.
Дэвид Х
39
POST-запросы не идемпотентны, что означает, что они не должны кэшироваться, если ответ не рекомендует делать это через свои заголовки ответа.
Джеймс М. Грин
4
Как говорит Дэвид, это явное нарушение предложения, которое вы цитировали. Если нет «полей заголовка Cache-Control или Expires», соответствующие такие заголовки, очевидно, не включены. Тем не менее, ваше собственное расследование показывает, что в этом сценарии он кешируется. Пожалуйста, отредактируйте свой ответ.
Мэтью Флэшен
3
Кто-нибудь знает, как долго результат кешируется на устройстве? Я пытался убить сафари и перезагрузить телефон, но он все еще кешируется. Я знаю, что это работает с очисткой кэша браузера, но мне интересно, сколько времени потребуется пользователям, у которых однажды возникла проблема, прежде чем она исчезнет. Не все будут думать о том, чтобы очистить свой кеш ...
Даниэль Халлквист,
146

Я надеюсь, что это может быть полезно для других разработчиков, которые бьют головой об стену на этом. Я обнаружил, что любое из следующих действий не позволяет Safari на iOS 6 кэшировать ответ POST:

  • добавление [cache-control: no-cache] в заголовки запроса
  • добавление переменного URL-параметра, такого как текущее время
  • добавление [pragma: no-cache] в заголовки ответа
  • добавление [cache-control: no-cache] в заголовки ответа

Мое решение было следующим в моем Javascript (все мои запросы AJAX POST).

$.ajaxSetup({
    type: 'POST',
    headers: { "cache-control": "no-cache" }
});

Я также добавляю заголовок [pragma: no-cache] ко многим ответам моего сервера.

Если вы используете вышеупомянутое решение, имейте в виду, что любые вызовы $ .ajax (), которые вы делаете, имеют глобальный характер: false НЕ будут использовать параметры, указанные в $ .ajaxSetup (), поэтому вам нужно будет снова добавить заголовки.

Дейв
источник
4
Это правильное решение ошибки. Ошибка заключается в том, что iOS 6 будет обслуживать POST-запросы из своего кэша, а не отправлять их на сервер. Ошибка не в том, что она кеширует ответы от запросов POST (что разрешено). Если вы все еще хотите, чтобы ответы на POST-запросы извлекались из кэша для последующих GET-запросов к этому URI, используйте это решение.
Николас Шенкс
2
Это работает для меня, но я не понимаю как. Я уже указал cache: false в моем ajaxSetup и, глядя на заголовки запросов, сводится к Cache-Control: no-cache и Pragma: no-cache - но он все равно будет кэшироваться на iPad. Затем, когда я добавляю заголовки: {"cache-control": "no-cache"} в ajaxSetup, он удваивает заголовок Cache-Control до "no-cache, no-cache" - и останавливает кэширование. Что тут происходит?
Том Зал
Работает отлично - вы также можете добавить к запросу параметр $ .ajax ({тип: 'POST', заголовки: {'cache-control': 'no-cache'} и т. Д.})
Джордж Филиппакос
Что такое [прагма: без кеша]? Для чего нужен ключ прагмы?
Закданс
Я также думаю, что это лучший подход, а не обходной путь с дополнительным параметром. Мы добавили это только к тем вызовам, которые нам нужны, для вызовов, которые всегда имеют одинаковый возврат, кэширование, вероятно, является хорошей вещью для конечного пользователя.
Germankiwi
67

Простое решение для всех ваших запросов веб-службы, если вы используете jQuery:

$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
    // you can use originalOptions.type || options.type to restrict specific type of requests
    options.data = jQuery.param($.extend(originalOptions.data||{}, { 
      timeStamp: new Date().getTime()
    }));
});

Узнайте больше о вызове префильтра jQuery здесь .

Если вы не используете jQuery, проверьте документацию для вашей библиотеки по вашему выбору. Они могут иметь схожую функциональность.

Baz1nga
источник
3
Мне это не работает, сервер отвечает: «Недопустимый примитив JSON: timeStamp» asp.net / iis 7.5
Александр,
3
как насчет $ .ajax ({"cache": false ...})? это будет работать при добавлении _ = [TIMESTAMP]? (У меня нет такого устройства для его тестирования)
Karussell
Я опубликовал полную реализацию решения, предложенного Karussell. Смотрите мой ответ ниже.
Сэм Шилс
1
@Karussell. Только что попытался установить $ .ajax ({"cache": false ...}). Это не решает проблему для запросов POST на iOS6. Предположительно, потому что JQuery согласно их документам предполагает, что ни один браузер не настолько глуп, чтобы кэшировать почтовые запросы. «Страницы, полученные с помощью POST, никогда не кэшируются, поэтому параметры cache и ifModified в jQuery.ajaxSetup () не влияют на эти запросы».
Бретт Ханна
1
Это не работает Он не объединяет параметры сообщения. Пост Дэйва - лучшее решение.
Крис Мюнх
43

У меня только что была эта проблема в приложении PhoneGap . Я решил это с помощью функции JavaScript getTime()следующим образом:

var currentTime = new Date();
var n = currentTime.getTime();
postUrl = "http://www.example.com/test.php?nocache="+n;
$.post(postUrl, callbackFunction);

Я потратил несколько часов, чтобы понять это. Было бы неплохо, чтобы Apple уведомила разработчиков об этой проблеме с кэшированием.

Башевис
источник
1
Я собирался прокомментировать использование {cache:false}в качестве опции либо, $.post()либо $.ajaxSetup(), но, согласно документации , эти аргументы игнорируются; jQuery никогда не будет кешировать почтовые запросы, но не учитывает браузер. Возможно, более аккуратным вариантом будет добавление метки времени к запросам, использующим $.ajaxPrefilter().
fwielstra
я потратил почти 5 часов, чтобы исправить эту проблему, и, наконец, добавление метки времени сделает function send_ajax(my_data,refresh)
свое дело
42

У меня была та же проблема с веб-приложением, получающим данные из веб-службы ASP.NET

Это сработало для меня:

public WebService()
{
    HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    ...
}
Tadej
источник
2
Большое спасибо! Я сходил с ума, пытаясь понять, почему iPhone действует так сильно, как любая другая платформа. Это решение для ASP.NET сэкономило мне массу времени.
Марк Бриттингем
Не работал на iOS6, смотрите мой ответ в конце темы
Брайан Огден,
1
Пожалуйста!!!! Поставьте условие, чтобы применять это только в IOS 6, кэш контента жизненно важен для любого приложения.
Александр
24

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

В JavaScript:

var xhr = new XMLHttpRequest();
xhr.open("post", 'uploader.php', true);
xhr.setRequestHeader("pragma", "no-cache");

В PHP :

header('cache-control: no-cache');
goker.cebeci
источник
15

Из моего собственного блога iOS 6.0 кеширует AJAX POST-запросы :

Как это исправить: Существуют различные способы предотвращения кэширования запросов. Рекомендуемый метод - добавление заголовка без кэширования. Вот как это делается.

JQuery:

Проверьте для iOS 6.0 и установите заголовок Ajax следующим образом:

$.ajaxSetup({ cache: false });

ZeptoJS:

Проверьте для iOS 6.0 и установите заголовок Ajax следующим образом:

$.ajax({
    type: 'POST',
    headers : { "cache-control": "no-cache" },
    url : ,
    data:,
    dataType : 'json',
    success : function(responseText) {…}

Серверная сторона

Ява:

httpResponse.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");

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

.СЕТЬ

Response.Cache.SetNoStore();

Или

Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);

PHP

header('Cache-Control: no-cache, no-store, must-revalidate'); // HTTP 1.1.
header('Pragma: no-cache'); // HTTP 1.0.
kiranvj
источник
2
Хороший атрибут отсутствия кэша для .NET stackoverflow.com/questions/10011780/…
Аран Малхолланд
7

Этот фрагмент JavaScript прекрасно работает с jQuery и jQuery Mobile:

$.ajaxSetup({
    cache: false,
    headers: {
        'Cache-Control': 'no-cache'
    }
});

Просто поместите его где-нибудь в своем коде JavaScript (после загрузки jQuery и лучше всего перед выполнением запросов AJAX), и это должно помочь.

Джонатан
источник
6

Вы также можете решить эту проблему, изменив jQuery Ajax функцию , выполнив следующее (начиная с 1.7.1) в верхней части функции Ajax (функция начинается со строки 7212). Это изменение активирует встроенную функцию анти-кэширования jQuery для всех запросов POST.

(Полный сценарий доступен на http://dl.dropbox.com/u/58016866/jquery-1.7.1.js .)

Вставьте ниже строки 7221:

if (options.type === "POST") {
    options.cache = false;
}

Затем измените следующее (начиная со строки ~ 7497).

if (!s.hasContent) {
    // If data is available, append data to URL
    if (s.data) {
        s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
        // #9682: remove data so that it's not used in an eventual retry
        delete s.data;
    }

    // Get ifModifiedKey before adding the anti-cache parameter
    ifModifiedKey = s.url;

    // Add anti-cache in URL if needed
    if (s.cache === false) {
        var ts = jQuery.now(),
        // Try replacing _= if it is there
        ret = s.url.replace(rts, "$1_=" + ts);

        // If nothing was replaced, add timestamp to the end.
        s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
    }
}

Для того, чтобы:

// More options handling for requests with no content
if (!s.hasContent) {
    // If data is available, append data to URL
    if (s.data) {
        s.url += (rquery.test(s.url) ? "&" : "?") + s.data;
        // #9682: remove data so that it's not used in an eventual retry
        delete s.data;
    }

    // Get ifModifiedKey before adding the anti-cache parameter
    ifModifiedKey = s.url;
}

// Add anti-cache in URL if needed
if (s.cache === false) {
    var ts = jQuery.now(),
    // Try replacing _= if it is there
    ret = s.url.replace(rts, "$1_=" + ts);

    // If nothing was replaced, add timestamp to the end.
    s.url = ret + ((ret === s.url) ? (rquery.test(s.url) ? "&" : "?") + "_=" + ts : "");
}
Сэм Шайлс
источник
4
Это не очень хороший подход, чтобы изменить jQuery или любой другой код, которым вы не владеете. (Каждый раз, когда вы хотите обновить версию, вам придется вносить изменения снова. (Или Другой разработчик обновляется, и программа не работает))
andlrc
Это совершенно обоснованный подход, если вам нужно самое быстрое решение для смягчения идиотизма Apple. Это решение было использовано для решения проблемы для массивного сайта, который получает миллионы посещений в день, и это позволило нам сделать это, просто внеся изменения в один файл.
Сэм Шайлс
Вы можете посмотреть, jQuery.ajaxPrefilerкак вы можете изменить свой AJAX-запрос прямо перед его выполнением. Вы можете архивировать то же самое с более оптимизированным и обновлять безопасный код.
andlrc
1
Проблема с подходом preFilter заключается в том, что вам необходимо зарегистрировать фильтр. Если у вас есть общий сценарий, который запускается при загрузке каждой страницы, то это нормально, но если вы этого не сделаете, вам придется настроить preFilter для каждой страницы, которая использует ajax. Сценарий, с которым я столкнулся, имел общее местоположение для файла JQ, который использовался в качестве ресурса для 7+ отдельных веб-сайтов. Из-за этой ошибки мы теряли тысячи фунтов в час, и предложенный мною подход позволил нам решить ее в кратчайшие сроки, изменив ОДИН файл. Я согласен с вами в принципе, но иногда вы должны быть прагматичными!
Сэм Шайлс
Затем вы можете снова добавить его в конец этого файла. Хорошо, что вы решили это, ваша компания должна быть рада за вас.
andlrc
5

Быстрый обходной путь для служб GWT-RPC - добавить это ко всем удаленным методам:

getThreadLocalResponse().setHeader("Cache-Control", "no-cache");
Ларс Хёйдал
источник
У большинства из нас есть сотни удаленных методов в их развертываниях GWT. Есть ли универсальный способ установить заголовок управления кешем для всех запросов?
Дирконейл
5

Это обновление ответа Baz1nga. Поскольку options.dataэто не объект, а строка, я просто прибег к конкатенации метки времени:

$.ajaxPrefilter(function (options, originalOptions, jqXHR) {
  if (originalOptions.type == "post" || options.type == "post") {

    if (options.data && options.data.length)
      options.data += "&";
    else
      options.data = "";

    options.data += "timeStamp=" + new Date().getTime();
  }
});
remcoder
источник
1
Добавление временных меток - плохая идея, вместо этого попробуйте решение Дэйва.
Николас Шенкс
4

Чтобы решить эту проблему для WebApps, добавленных на домашний экран, необходимо следовать обоим лучшим решениям. Кэширование должно быть отключено на веб-сервере, чтобы предотвратить дальнейшее кэширование новых запросов, и необходимо добавлять некоторые случайные входные данные в каждый пост-запрос, чтобы запросы, которые уже были кэшированы, проходили. Пожалуйста, обратитесь к моему сообщению:

iOS6 - Есть ли способ очистить кэшированные запросы POST ajax для веб-приложения, добавленные на домашний экран?

ВНИМАНИЕ: всем, кто внедрил обходной путь, добавив временную метку к своим запросам, не отключая кэширование на сервере. Если ваше приложение добавлено на домашний экран, КАЖДЫЙ пост-ответ теперь будет кэшироваться, очистка кэша сафари не очищает его и, похоже, не истекает. Если у кого-то нет способа очистить его, это выглядит как потенциальная утечка памяти!

fbader
источник
Будут ли кэшированы все ответы в файл или память телефона?
Эйдун
Это было не так со мной. Я добавил метку времени к своему URL (а не к параметрам публикации), и она отлично работает, как при просмотре в Safari, так и при сохранении на главном экране.
ShadeTreeDeveloper
4

Вещи, которые не работали для меня с iPad 4 / iOS 6:

Мой запрос, содержащий: Cache-Control: no-cache

//asp.net's:
HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache)

Добавление кэша: false для моего вызова jQuery ajax

 $.ajax(
        {
            url: postUrl,
            type: "POST",
            cache: false,
            ...

Только это добилось цели:

var currentTime = new Date();
var n = currentTime.getTime();
postUrl = "http://www.example.com/test.php?nocache="+n;
$.post(postUrl, callbackFunction);
Брайан Огден
источник
За что проголосовал против? Это кэш важной информации: false не работает с iPad4 / iOS6, а также //asp.net: HttpContext.Current.Response.Cache.SetCacheability (HttpCacheability.NoCache)
Брайан Огден,
Для потомков: с 2017 года $.ajax cache: falseдобавляется URL с параметром запроса _=Date.prototype.getTime(), поэтому добавление временной метки вручную больше не требуется.
Cowbert
3

Это обходной путь для GWT-RPC

class AuthenticatingRequestBuilder extends RpcRequestBuilder 
{
       @Override
       protected RequestBuilder doCreate(String serviceEntryPoint) 
       {
               RequestBuilder requestBuilder = super.doCreate(serviceEntryPoint);           
               requestBuilder.setHeader("Cache-Control", "no-cache");

               return requestBuilder;
       }
}

AuthenticatingRequestBuilder builder = new AuthenticatingRequestBuilder();
((ServiceDefTarget)myService).setRpcRequestBuilder(builder);    
Spiff
источник
2

Мой обходной путь в ASP.NET (методы страницы, веб- сервис и т. Д.)

protected void Application_BeginRequest(object sender, EventArgs e)
{
    Response.Cache.SetCacheability(HttpCacheability.NoCache);
}
Александр
источник
1

Хотя добавление параметров cache-buster для того, чтобы запрос выглядел по-другому, выглядит как надежное решение, я бы посоветовал против него, так как это повредит любому приложению, которое полагается на фактическое кэширование. Обеспечение правильного вывода заголовков API-интерфейсов является наилучшим возможным решением, даже если это немного сложнее, чем добавление кешей для вызывающих.

Иво Янш
источник
1
Хотя я согласен с вами в большинстве случаев, я бы сказал, что реальное решение этой проблемы для Apple - правильно реализовать HTTP. Имея это в виду, я бы не стал обвинять многих разработчиков в реализации самого простого из возможных решений до того времени. Для меня изменение реализации jquery было самым простым исправлением, поскольку оно позволило мне сделать одно редактирование и быть уверенным, что оно активно для всего моего сайта.
Сэм Шилс,
1

Для тех, кто использует Struts 1 , вот как я исправил проблему.

web.xml

<filter>
    <filter-name>SetCacheControl</filter-name>
    <filter-class>com.example.struts.filters.CacheControlFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>SetCacheControl</filter-name>
    <url-pattern>*.do</url-pattern>
    <http-method>POST</http-method>
</filter-mapping>

com.example.struts.filters.CacheControlFilter.js

package com.example.struts.filters;

import java.io.IOException;
import java.util.Date;
import javax.servlet.*;
import javax.servlet.http.HttpServletResponse;

public class CacheControlFilter implements Filter {

        public void doFilter(ServletRequest request, ServletResponse response,
                     FilterChain chain) throws IOException, ServletException {

        HttpServletResponse resp = (HttpServletResponse) response;
        resp.setHeader("Expires", "Mon, 18 Jun 1973 18:00:00 GMT");
        resp.setHeader("Last-Modified", new Date().toString());
        resp.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0");
        resp.setHeader("Pragma", "no-cache");

        chain.doFilter(request, response);
    }

    public void init(FilterConfig filterConfig) throws ServletException {
    }

    public void destroy() {
    }

}
cbmeeks
источник
1

Я смог исправить свою проблему, используя комбинацию $ .ajaxSetup и добавив метку времени к URL-адресу моего сообщения (не к параметрам / телу сообщения). Это основано на рекомендациях предыдущих ответов

$(document).ready(function(){
    $.ajaxSetup({ type:'POST', headers: {"cache-control","no-cache"}});

    $('#myForm').submit(function() {
        var data = $('#myForm').serialize();
        var now = new Date();
        var n = now.getTime();
        $.ajax({
            type: 'POST',
            url: 'myendpoint.cfc?method=login&time='+n,
            data: data,
            success: function(results){
                if(results.success) {
                    window.location = 'app.cfm';
                } else {
                    console.log(results);
                    alert('login failed');
                }
            }
        });
    });
});
ShadeTreeDeveloper
источник
1

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

Это правда, что вы можете добавить много заголовков на каждом используемом вами языке, на стороне сервера, на стороне клиента, и вы можете использовать множество других приемов, чтобы избежать веб-кэширования, но всегда думайте, что вы никогда не узнаете, откуда клиент подключается к вашему серверу, Вы никогда не знаете, использует ли он соединение «Hot-Spot» в отеле, которое использует Squid или другие продукты для кеширования.

Если пользователи используют прокси, чтобы скрыть свою реальную позицию и т. Д., Реальный единственный способ избежать кэширования - это отметка времени в запросе, даже если она не используется.

Например:

/ajax_helper.php?ts=3211321456

Тогда каждый менеджер кеша, который вы должны передать, не нашел тот же URL в хранилище кеша и перезагружал содержимое страницы.

Ланелло
источник
Старый ответ, но мои два цента: как правило, это хороший совет, и его понимают большинство компетентных веб-разработчиков, но в конкретном случае jQuery, если вы сделаете $.ajaxи настроите параметры, чтобы иметь, {cache:false}то сам jQuery автоматически добавит очистку кеша за кулисами, без необходимости делать что-либо еще.
JakeGould
0

В зависимости от приложения, вы можете решить проблему сейчас в iOS 6, используя Safari> Дополнительно> Веб-инспектор, что поможет в этой ситуации.

Подключите телефон к Safari на Mac, а затем используйте меню разработчика для поиска неисправностей в веб-приложении.

Очистите данные веб-сайта на iPhone после обновления до iOS6, в том числе специфичные для приложения с помощью веб-представления. Только у одного приложения была проблема, и это решило ее во время бета-тестирования IOS6, с тех пор никаких реальных проблем не было.

Вам также может понадобиться взглянуть на ваше приложение, проверьте NSURLCache, если есть в WebView в пользовательском приложении.

https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSURLCache_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40003754

Я думаю, в зависимости от истинной природы вашей проблемы, реализации и т. Д ..

Ссылка: $ .ajax звонки

Стивен Штраус
источник
Хотя этот вопрос не касается непосредственно исходного вопроса, это очень полезная информация для возможности устранения неполадок на устройствах в целом, поэтому я проголосую за него.
Крис Гизинг
0

Я нашел один обходной путь, который заставляет меня интересоваться, почему это работает. Прежде чем прочитать ответ Тадея о веб-сервисе ASP.NET, я пытался придумать что-нибудь, что сработало бы.

И я не говорю, что это хорошее решение, но я просто хотел документировать его здесь.

главная страница: включает функцию JavaScript, checkStatus (). Этот метод вызывает другой метод, который использует вызов jQuery AJAX для обновления содержимого html. Я использовал setInterval для вызова checkStatus (). Конечно, я столкнулся с проблемой кеширования.

Решение: используйте другую страницу для вызова обновления.

На главной странице я установил логическую переменную runUpdate и добавил следующее в тег body:

<iframe src="helper.html" style="display: none; visibility: hidden;"></iframe>

В файле helper.html:

<meta http-equiv="refresh" content="5">
<script type="text/javascript">
    if (parent.runUpdate) { parent.checkStatus(); }
</script>

Итак, если checkStatus () вызывается с главной страницы, я получаю кэшированное содержимое. Если я вызываю checkStatus со страницы ребенка, я получаю обновленный контент.

CM Kanode
источник
0

Хотя мои страницы входа в систему и регистрации работают в Firefox, IE и Chrome, как чудо ... Я боролся с этой проблемой в Safari для IOS и OSX, несколько месяцев назад я нашел обходной путь для SO.

<body onunload="">

ИЛИ через JavaScript

<script type="text/javascript">
window.onunload = function(e){
    e.preventDefault();
    return;
};
</script>   

Это некрасиво, но работает какое-то время.

Я не знаю почему, но возвращая ноль к onunloadсобытию, страница не кэшируется в Safari.

Адриано Роза
источник
0

Мы обнаружили, что старые iPhone и iPad, работающие под управлением iOS версий 9 и 10, иногда возвращают фиктивные пустые результаты AJAX, возможно, из-за снижения скорости процессора Apple. При возврате пустого результата iOS не вызывает сервер, как если бы возвращал результат из кеша. Частота варьируется в широких пределах, примерно от 10% до 30% вызовов AJAX возвращаются пустыми.

Решение трудно поверить. Просто подождите 1 с и позвоните снова. В нашем тестировании только одно повторение было всем, что когда-либо было необходимо, но мы написали код для вызова до 4 раз. Мы не уверены, требуется ли ожидание 1 с, но мы не хотели рисковать, обременяя наш сервер пакетами повторных вызовов.

Мы обнаружили, что проблема произошла с двумя разными вызовами AJAX, которые вызывали разные файлы API с разными данными. Но я обеспокоен тем, что это может произойти при любом вызове AJAX. Мы просто не знаем, потому что мы не проверяем каждый результат AJAX и не проверяем каждый вызов несколько раз на старых устройствах.

Оба проблемных вызова AJAX использовали: POST, Asynchronously = true, setRequestHeader = ('Content-Type', 'application / x-www-form-urlencoded')

Когда возникает проблема, обычно происходит только один вызов AJAX. Так что это не из-за перекрывающихся вызовов AJAX. Иногда проблема возникает, когда устройство занято, но иногда нет, и без DevTools мы не знаем, что происходит в данный момент.

iOS 13 не делает этого, ни Chrome или Firefox. У нас нет тестовых устройств под управлением iOS 11 или 12. Возможно, кто-то еще мог бы протестировать их?

Я отмечаю это здесь, потому что этот вопрос является лучшим результатом Google при поиске этой проблемы.

CaptureWiz
источник
-1

Он работал с ASP.NET только после добавления pragma:no-cacheзаголовка в IIS . Cache-Control: no-cacheбыло недостаточно.

Борис
источник
-2

Я предлагаю обходной путь, чтобы изменить сигнатуру функции так:

getNewRecordID (intRecordType, strTimestamp) и затем всегда передают также параметр TimeStamp и просто отбрасывают это значение на стороне сервера. Это работает вокруг проблемы.

fred1234
источник