javascript - русском - скачать сафари на мак




Является ли Safari iOS 6 кэшированием $.ajax результатов? (17)

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

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

getNewRecordID(intRecordType)

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

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

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

getNewRecordID(intRecordType, strTimestamp)

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


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

getThreadLocalResponse().setHeader("Cache-Control", "no-cache");

В Синатре Руби

before '*' do
  if env['REQUEST_METHOD'] == 'POST'
    headers 'Cache-Control' => 'no-cache, no-store, must-revalidate'
  end
end

Вещи, которые НЕ РАБОТАЮТ для меня с iPad 4 / iOS 6:

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

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

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

 $.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);

Вы также можете исправить эту проблему, изменив функцию 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 : "");
}

Из моего собственного сообщения в блоге 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.

Мое обходное решение в ASP.NET (pagemethods, webservice и т. Д.)

protected void Application_BeginRequest(object sender, EventArgs e)
{
    Response.Cache.SetCacheability(HttpCacheability.NoCache);
}

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

В JavaScript:

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

В PHP :

header('cache-control: no-cache');

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


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


Простое решение для всех ваших запросов веб-сервисов, предполагая, что вы используете 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()
    }));
});

Подробнее о вызове prefilter jQuery.

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


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

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

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


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

<body onunload="">

ИЛИ через javascript

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

Это своего рода уродливая вещь, но работает какое-то время.

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


Это обновление ответа 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();
  }
});

Это работа для 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);    

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

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

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

Например:

/ajax_helper.php?ts=3211321456

Затем каждый менеджер кэша, который вы должны пройти, не нашел тот же URL-адрес в репозитории кеша и не перегрузил содержимое страницы.


Я нашел одно обходное решение, из-за которого мне стало интересно, почему это работает. Прежде чем прочитать ответ Тадея о веб-сервисе 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 с дочерней страницы, я получаю обновленный контент.


Я смог исправить свою проблему, используя комбинацию $ .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');
                }
            }
        });
    });
});




mobile-safari