İOS 6'da Safari $ .ajax sonuçlarını önbelleğe alıyor mu?


1072

İOS 6'ya yükseltme yaptığımızdan beri, Safari'nin web görünümünün önbellek $.ajaxaramalarının özgürlüğünü aldığını görüyoruz . Bu bir PhoneGap uygulaması bağlamındadır, bu yüzden Safari WebView kullanıyor. Bizim $.ajaxaramalar POSTyöntemler ve biz false önbellek kümesine sahip {cache:false}, ama yine de bu oluyor. TimeStampBaşlıklara manuel olarak bir ekleme yapmayı denedik , ancak yardımcı olmadı.

Daha fazla araştırma yaptık ve Safari'nin yalnızca işlev imzası statik olan ve çağrıdan çağrıya değişmeyen web hizmetleri için önbelleğe alınmış sonuçlar döndürdüğünü bulduk. Örneğin, şöyle bir işlevi düşünün:

getNewRecordID(intRecordType)

Bu işlev tekrar tekrar aynı giriş parametrelerini alır, ancak döndürdüğü veriler her seferinde farklı olmalıdır.

Önbellek ayarlarından çok mutlu oldukları iOS 6'yı etkileyici bir şekilde yapmak için Apple'ın acelesi olmalı. Bu davranışı iOS 6'da başka kimse gördü mü? Eğer öyleyse, tam olarak neye sebep oluyor?


Bulduğumuz geçici çözüm, işlev imzasını şu şekilde değiştirmekti:

getNewRecordID(intRecordType, strTimestamp)

ve her zaman bir TimeStampparametre de iletin ve sunucu tarafında bu değeri atın. Bu sorunu giderir. Umarım bu benim yaptığım gibi bu konuda 15 saat harcayan diğer bazı fakir ruhlara yardımcı olur!


190
Bu kesinlikle şok edici. Ayrıca, bir şeyin çalışmayı bıraktığı şeyi çözmeye çalışmak için birkaç saat geçirdik. POST yapan (ve önbelleğe almayı önlemek için üstbilgileri de olan) AJAX giriş bilgilerimiz Safari tarafından önbelleğe alınır, bu yüzden sunucuyu denemeden son kez yaptığı JSON ile aynı şeyi döndürür ... inanılmaz! Bir düzeltmeyi hacklememiz gerekecek, ancak asla bir POST'u önbelleğe almamalısınız, bu delilik.
Kieran

16
Sorunuzu güncellemek yerine çözümünüzü yanıt olarak gönderin.
ChrisF

50
POST istekleri onlar önbelleğe edilmemelidir vasıta olmayan İdempotent vardır sürece yanıtı özellikle onun yanıt başlıkları aracılığıyla bunu yaparken önerir.
James M. Greene

6
Apple'ın bunu düzeltmesini sağlamak için bugreport.apple.com adresine bir hata gönderin . Ben de aynısını yaptım.
Mathias Bynens

11
Mark Nottingham (IETF HTTPbis çalışma grubunun başkanı) bugün bunun hakkında ilginç bir blog yazısı yazdı: mnot.net/blog/2012/09/24/caching_POST
Benjamin Brizzi

Yanıtlar:


447

Biraz araştırma yapıldıktan sonra, iOS6'daki Safari'nin Önbellek Kontrolü üstbilgileri veya hatta "Önbellek Denetimi: maks. Yaş = 0" olan POST'ları önbelleğe alacağı ortaya çıktı.

Bu önbelleğe almanın, hizmet çağrılarının sonunda rasgele sorgu dizelerini kesmek zorunda kalmak yerine, küresel düzeyde olmasını engellemenin tek yolu "Önbellek Denetimi: önbellek yok" olarak ayarlamaktır.

Yani:

  • Cache-Control veya Expires üstbilgisi yok = iOS6 Safari önbellekleyecek
  • Önbellek Denetimi maks. Yaş = 0 ve hemen Son kullanma tarihi = iOS6 Safari önbellekleyecek
  • Önbellek Kontrolü: no-cache = iOS6 Safari önbellek ETMEZ

Apple bundan POST hakkında bölüm 9.5 HTTP spec bu yararlanıyor şüpheli:

Yanıt uygun Önbellek Denetimi veya Süresi Sonu başlık alanlarını içermediği sürece, bu yönteme verilen yanıtlar önbelleğe alınamaz. Bununla birlikte, 303 (Diğerlerine Bak) yanıtı, kullanıcı aracısını önbelleğe alınabilir bir kaynağı almaya yönlendirmek için kullanılabilir.

Böylece teoride POST yanıtlarını önbelleğe alabilirsiniz ... kim bilir. Ancak şimdiye kadar başka bir tarayıcı üreticisi bunun iyi bir fikir olacağını düşünmemişti. Ancak hiçbir Önbellek Denetimi veya Sona Erme başlıkları ayarlanmadığında, yalnızca bazı kümeler olduğunda önbelleği dikkate almaz. Bu yüzden bir hata olmalı.

Aşağıda, API'mın tamamını hedeflemek için Apache yapılandırmamın sağ bitinde kullandığım şey var, çünkü gerçekte bir şey önbelleğe almak istemiyorum, hatta alır. Bilmiyorum sadece POSTs için bu nasıl ayarlanır.

Header set Cache-Control "no-cache"

Güncelleme: Sadece POST aynı olduğunda işaret etmediğimi fark ettim, bu yüzden POST verilerini veya URL'lerini değiştirin ve iyisiniz. Başka bir yerde belirtildiği gibi, URL'ye rastgele veriler veya biraz POST verisi ekleyebilirsiniz.

Güncelleme: Apache'de isterseniz "no-cache" yi yalnızca POST'larla sınırlayabilirsiniz:

SetEnvIf Request_Method "POST" IS_POST
Header set Cache-Control "no-cache" env=IS_POST

7
Apple'ın bununla nereye gittiğini görüyorum, ancak yanıtlarımız herhangi bir Cache-Control veya Expires üstbilgisi içermese bile POST isteklerine Önbellek yanıtları görüyoruz. Bu örnek iOS6'nın her isteği önbelleğe almaması ve göndermemesi gerekir. Bu gerçekleşmiyor.
Kango_V

138
Alıntı yaptığınız HTTP spesifikasyonu bölümü iOS 6'nın önbellekleme davranışını haklı çıkarmıyor. Varsayılan davranış POST yanıtlarını önbelleğe almamak olmalıdır (yani "Önbellek Denetimi" başlığı tanımlanmadığında). Davranış özellikleri ihlal eder ve bir hata olarak kabul edilmelidir. Xml / json api web hizmetleri oluşturan herkes bu soruna geçici bir çözüm bulmak için POST yanıtlarını "Önbellek denetimi: no-cache" ile dekore etmelidir.
David H

39
POST istekleri onlar önbelleğe edilmemelidir vasıta olmayan İdempotent vardır sürece yanıtı özellikle onun yanıt başlıkları aracılığıyla bunu yaparken önerir.
James M. Greene

4
David'in dediği gibi, alıntıladığınız cümlenin açık bir ihlali. "Cache-Control veya Expires başlık alanları" yoksa, bu tür uygun başlıklar kesinlikle dahil edilmez. Yine de kendi araştırmanız bu senaryoda önbellekleri gösteriyor. Lütfen cevabınızı düzenleyin.
Matthew Flaschen

3
Sonucun bir cihazda ne kadar süreyle önbelleğe alındığını bilen var mı? Safari'yi öldürmeyi ve telefonumu yeniden başlatmayı denedim, ancak yine de önbelleğe alınmış. Tarayıcı önbelleğini temizlemeyle çalıştığını biliyorum, ancak bir zamanlar sorun çıkmadan önce kullanıcılar için ne kadar süreceğini merak ediyorum. Herkes önbelleklerini temizlemeyi düşünmeyecek ...
Daniel Hallqvist

146

Umarım bu, bu konuda kafalarını duvara çarpan diğer geliştiriciler için yararlı olabilir. Aşağıdakilerden herhangi birinin iOS 6'daki Safari'nin POST yanıtını önbelleğe almasını engellediğini tespit ettim:

  • istek başlıklarına [cache-control: no-cache] ekleme
  • geçerli saat gibi değişken bir URL parametresi ekleme
  • yanıt başlıklarına [pragma: no-cache] ekleniyor
  • yanıt başlıklarına [cache-control: no-cache] ekleme

Benim çözüm (benim tüm AJAX istekleri POST) benim Javascript aşağıdaki idi.

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

Ayrıca sunucu yanıtlarımın çoğuna [pragma: no-cache] üstbilgisini ekliyorum.

Yukarıdaki çözümü kullanırsanız, global olarak ayarlanmış herhangi bir $ .ajax () çağrısının farkında olun: false, $ .ajaxSetup () öğesinde belirtilen ayarları KULLANMAYACAKTIR, bu nedenle üstbilgileri tekrar eklemeniz gerekir.


4
Bu hata için doğru çözümdür. Hata, iOS 6'nın POST isteklerini sunucuya göndermek yerine önbelleğinden sunmasıdır. Hata, POST isteklerinden gelen yanıtları önbelleğe alması değildir (buna izin verilir). Hala bu URI'ye GET istekleri için önbellekten alınan POST isteklerine yanıt almak istiyorsanız, bu çözümü kullanın.
Nicholas Shanks

2
Bu benim için çalışıyor, ama nasıl olduğunu anlamıyorum. Zaten ajaxSetup içinde önbellek: false belirttim ve Cache-Control: no-cache ve Pragma: no-cache için kaybolan istek başlıklarına baktım, ancak yine de iPad'de önbelleklenecek. Sonra ajaxSetup içine {: cache-control ":" no-cache "} üstbilgileri eklediğimde, Cache-Control üstbilgisini" no-cache, no-cache "olarak ikiye katlar ve önbelleği durdurur. Burada neler oluyor?
Tom W Hall

Mükemmel çalışır - isteğe ayrıca $ .ajax parametresi olarak ekleyebilirsiniz ({type: 'POST', üstbilgiler: {'cache-control': 'no-cache'}, vb.))
George Filippakos

[Pragma: no-cache] nedir? Pragma anahtarı ne için kullanılır?
zakdances

Ben de bu ek bir parametre ile bir geçici çözüm yerine, en iyi yaklaşım olduğunu düşünüyorum. Bunu sadece ihtiyaç duyduğumuz çağrılara ekledik, her zaman aynı dönüşe sahip çağrılar için önbellekleme muhtemelen son kullanıcı için iyi bir şey.
germankiwi

67

JQuery kullandığınızı varsayarsak, tüm web hizmeti istekleriniz için basit çözüm:

$.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 ön filtre çağrısı hakkında daha fazla bilgiyi buradan edinebilirsiniz .

JQuery kullanmıyorsanız, seçtiğiniz kitaplığın belgelerine bakın. Benzer işlevlere sahip olabilirler.


3
Bana çalışmıyor, sunucu yanıt veriyor: "Geçersiz ilkel JSON: timeStamp" asp.net / iis 7.5
Alexandre

3
$ .ajax ({"cache": false ...}) ne olacak? _ = [TIMESTAMP] eklediğinde çalışır mı? (Test etmek için böyle bir cihazım yok)
Karussell

Karussell tarafından önerilen çözümün tam uygulamasını yayınladım. Cevabımı aşağıda görebilirsiniz.
Sam Shiles

1
@Karussell. $ .Ajax ayarını denedim ({"cache": false ...}). Bu, iOS6'daki POST istekleriyle ilgili sorunu çözmez. Muhtemelen JQuery belgelerine göre hiçbir tarayıcı posta istekleri önbelleğe almak için yeterince aptal varsaymıyor çünkü. "POST ile getirilen sayfalar hiçbir zaman önbelleğe alınmaz, bu nedenle jQuery.ajaxSetup () içindeki önbellek ve ifModified seçeneklerinin bu istekler üzerinde hiçbir etkisi yoktur."
Brett Hannah

1
Bu işe yaramıyor. Yazı parametrelerini birleştirmez. Dave'in gönderisi daha iyi bir çözümdür.
Chris Muench

43

Bu sorunu bir PhoneGap uygulamasında da yaşadım . getTime()Aşağıdaki şekilde JavaScript işlevini kullanarak çözdüm:

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

Bunu anlamaya birkaç saat harcadım. Geliştiricilere bu önbellekleme sorununu bildirmek Apple için iyi olurdu.


1
Ben kullanımıyla ilgili açıklama gidiyordu {cache:false}bir seçenek olarak ya $.post()ya $.ajaxSetup(), ama uygun dokümanlar , bu argümanları göz ardı edilir; jQuery, yayın isteklerini hiçbir zaman 'önbelleğe almaz', ancak tarayıcıyı dikkate almaz. Belki daha temiz bir seçenek, kullanarak isteklere bir zaman damgası eklemek olacaktır $.ajaxPrefilter().
fwielstra

i bu sorunu çözmek için neredeyse 5 saat harcamak ve nihayet zaman damgası eklemek hile yapacak function send_ajax(my_data,refresh) .. buraya bakın stackoverflow.com/questions/14733772/…
rusya

42

ASP.NET web hizmetinden veri alma bir webapp ile aynı sorunu vardı

Bu benim için çalıştı:

public WebService()
{
    HttpContext.Current.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    ...
}

2
Çok teşekkür ederim! İPhone'un neden diğer platformlardan farklı davrandığını anlamaya çalışıyordum. Bu ASP.NET'e özgü çözüm bana tonlarca zaman kazandırdı.
Mark Brittingham

İOS6'da işe yaramadı, iş parçacığının sonuna doğru cevabımı gör
Brian Ogden

1
Lütfen!!!! Bunu yalnızca IOS 6'ya uygulamak için bir koşul koyun, içerik önbelleği herhangi bir uygulama için hayati önem taşır.
Alexandre

24

Son olarak, yükleme sorunuma bir çözüm buldum.

JavaScript'te:

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

In PHP :

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

15

Kendi blog yazımdan iOS 6.0, Ajax POST isteklerini önbelleğe alma :

Nasıl düzeltilir? İsteklerin önbelleğe alınmasını önlemek için çeşitli yöntemler vardır. Önerilen yöntem önbelleksiz bir başlık eklemektir. İşte böyle yapılır.

jQuery:

İOS 6.0'ı kontrol edin ve Ajax üstbilgisini şu şekilde ayarlayın:

$.ajaxSetup({ cache: false });

ZeptoJS:

İOS 6.0'ı kontrol edin ve Ajax üstbilgisini şu şekilde ayarlayın:

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

Sunucu tarafı

Java:

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

İstemciye herhangi bir veri gönderilmeden önce bunu sayfanın üstüne eklediğinizden emin olun.

.AĞ

Response.Cache.SetNoStore();

Veya

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.

2
.NET için iyi bir önbellek özelliği stackoverflow.com/questions/10011780/…
Aran Mulholland

7

Bu JavaScript snippet'i jQuery ve jQuery Mobile ile harika çalışıyor:

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

Sadece JavaScript kodunuzda bir yere yerleştirin (jQuery yüklendikten sonra ve AJAX istekleri yapmadan önce en iyisi) ve yardımcı olacaktır.


6

Bu sorunu ayrıca, Ajax işlevinin en üstüne aşağıdakileri (1.7.1'den itibaren) yaparak jQuery Ajax işlevini değiştirerek de çözebilirsiniz (işlev, 7212 satırından başlar). Bu değişiklik, tüm POST istekleri için jQuery'nin yerleşik önbellek önleme özelliğini etkinleştirir.

(Komut dosyasının tamamını şurada bulabilirsiniz http://dl.dropbox.com/u/58016866/jquery-1.7.1.js.)

7221 satırının altına ekleyin:

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

Sonra aşağıdakileri değiştirin (~ 7497 satırından başlayarak).

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 : "");
    }
}

Kime:

// 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 değiştirmek veya bu nedenle sahip olmadığınız herhangi bir kod için iyi bir yaklaşım değildir. (Sürümü güncellemek istediğinizde, değişikliği tekrar yapmanız gerekir. (Veya Başka bir geliştirici güncellemesi ve program çalışmaz))
andlrc

Apple'ın aptallığını azaltmak için mümkün olan en hızlı çözüme ihtiyacınız varsa, mükemmel geçerli bir yaklaşımdır. Bu çözüm, günde milyonlarca isabet alan devasa bir sitenin sorununu çözmek için kullanıldı ve sadece bir dosyada değişiklik yaparak bunu yapmamızı sağladı.
Sam Shiles

En Bakabilirsin jQuery.ajaxPrefilero bunu yapmadan önce ajax isteği hakkına değiştirmenize olanak tanır. Aynı şeyi daha optimize ve güvenli kodla arşivleyebilirsiniz.
andlrc

1
Ön Filtre yaklaşımı ile ilgili sorun, filtreyi kaydetmeniz gerektiğidir. Her sayfa yüklendiğinde çalışan ortak bir komut dosyanız varsa, iyi, ancak yoksa, ajax kullanan her sayfa için ön Filtreyi ayarlamanız gerekir. Karşılaştığım senaryo, JQ dosyası için 7+ web sitesi için kaynak olarak kullanılan ortak bir konumumuz vardı. Bu hata nedeniyle saatte binlerce pound kaybediyorduk ve önerdiğim yaklaşım ONE dosyasını değiştirerek en kısa sürede çözüme kavuşturmamızı sağladı. Prensipte sana katılıyorum ama bazen pragmatik olmalısın!
Sam Shiles

Daha sonra tekrar bu dosyanın sonuna ekleyebilirsiniz. Çözdünüz mü, şirketiniz sizin için mutlu olmalı.
andlrc

5

GWT-RPC hizmetleri için hızlı bir çözüm, bunu tüm uzak yöntemlere eklemektir:

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

Çoğumuz GWT dağıtımlarında yüzlerce uzak yönteme sahibiz. Tüm istekler için önbellek denetim başlığını ayarlamanın evrensel bir yolu var mı?
dirkoneill

5

Bu Baz1nga'nın cevabının bir güncellemesidir. Çünkü options.databir nesne değil, sadece bir zaman damgasını bitiştirmeye başvurduğum bir dize:

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

1
Zaman damgaları eklemek kötü bir fikirdir, bunun yerine Dave'in çözümünü deneyin.
Nicholas Shanks

4

Ana ekrana eklenen WebApp'ları için bu sorunu çözmek için en iyi oy alan geçici çözümlerin her ikisinin de izlenmesi gerekir. Yeni isteklerin önbelleğe alınmasını önlemek için web sunucusunda önbelleğe almanın kapatılması ve önceden önbelleğe alınmış isteklerin gerçekleşmesi için her gönderi isteğine bazı rastgele girdilerin eklenmesi gerekir. Lütfen yazıma bakın:

iOS6 - Ana ekrana eklenen webapp için önbelleğe alınmış ajax POST isteklerini temizlemenin bir yolu var mı?

UYARI: sunucudaki önbelleği kapatmadan isteklerine bir zaman damgası ekleyerek bir geçici çözüm uygulayan herkese. Uygulamanız ana ekrana eklenirse, HER gönderi yanıtı şimdi önbelleğe alınacak, safari önbelleğini temizlemek uygulamayı temizlemiyor ve süresi dolmuyor gibi görünüyor. Birisi temizlemek için bir yolu yoksa, bu potansiyel bir bellek sızıntısı gibi görünüyor!


Tüm yanıtlar telefondaki dosyaya veya belleğe önbelleğe alınacak mı?
Eydun

Bu benim için geçerli değildi. URL'ye (posta parametrelerine değil) bir zaman damgası ekledim ve hem safari'den göz atarken hem de ana ekrana kaydederken iyi çalışıyor.
ShadeTreeDeveloper

4

Bir iPad 4 / iOS 6 ile benim için ÇALIŞMAYAN şeyler :

Aşağıdakileri içeren isteğim: Cache-Control: no-cache

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

JQuery ajax çağrıma önbellek ekleme: false

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

Sadece bu hile yaptı:

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

Aşağı oy ne işe yarıyor? Bu önemli bir bilgi önbelleğidir: false, iPad4 / iOS6 ile çalışmaz veya //asp.net'in: HttpContext.Current.Response.Cache.SetCacheability (HttpCacheability.NoCache)
Brian Ogden

Posterity için: 2017 itibariyle, $.ajax cache: falseurl'yi sorgu parametresiyle ekler _=Date.prototype.getTime(), bu nedenle zaman damgasını manuel olarak eklemek artık gerekli değildir.
cowbert

3

GWT-RPC için bu çözüm

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

2

ASP.NET'teki geçici çözümüm (pagemethods, webservice vb.)

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

1

İsteğin farklı görünmesini sağlamak için önbellek bozucu parametreleri eklemek sağlam bir çözüm gibi görünse de, gerçekleşen önbelleğe almayı gerektiren herhangi bir uygulamayı inciteceği için buna karşı tavsiye ederim. Arayanlara önbellek bozucu eklemekten biraz daha zor olsa bile, API'lerin doğru başlıkların çıkmasını sağlamak mümkün olan en iyi çözümdür.


1
Size çoğu koşulda katılıyorum, ancak bu sorunun gerçek çözümünün Apple'ın HTTP'yi doğru bir şekilde uygulaması olduğunu iddia ediyorum. Bunu göz önünde bulundurarak, o zamana kadar mümkün olan en basit çözümü uygulamak için pek çok geliştiriciyi suçlamam. Benim için, jquery uygulamasını değiştirmek, bir düzenleme yapmama ve tüm sitem için aktif olduğundan emin olmam için en basit bir düzeltmeydi.
Sam Shiles

1

Kullananlar için Struts 1, burada Sorunu sabit nasıl.

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() {
    }

}

1

Ben $ .ajaxSetup bir kombinasyonu kullanarak ve benim yazı url (posta parametreleri / vücut değil) bir zaman damgası ekleyerek sorunumu düzeltmek mümkün. Bu, önceki cevapların önerilerine dayanarak

$(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');
                }
            }
        });
    });
});

1

Sorununuzu zaten çözdüğünüzü düşünüyorum, ancak web önbelleğe alma hakkında bir fikir paylaşmama izin verin.

Kullandığınız her dilde, sunucu tarafında, istemci tarafında birçok başlık ekleyebileceğiniz ve web önbelleğini önlemek için diğer birçok hile kullanabileceğiniz doğrudur, ancak her zaman istemcinin sunucunuza nereden bağlandığını asla bilemeyeceğinizi düşünür, Squid veya diğer önbellekleme ürünlerini kullanan bir Otel “Hot-Spot” bağlantısı kullanıp kullanmadığını asla bilemezsiniz.

Kullanıcıların vb onun gerçek konumunu, gizlemek için vekil kullanıyorsanız ... gerçek önlemek önbelleğe alma için tek yol kullanılmayan ayrıca eğer istekte damgası olduğunu.

Örneğin:

/ajax_helper.php?ts=3211321456

Daha sonra geçmeniz gereken her önbellek yöneticisi, önbellek deposunda aynı URL'yi bulamadı ve sayfa içeriğini yeniden indirmeye gitti.


Eski cevap, ama benim iki sent: Bu genellikle iyi bir tavsiye ve en yetkili web geliştiricileri tarafından anlaşılır, ancak belirli bir jQuery durumunda, bir $.ajaxseçenek yaparsanız ve varsa seçenekleri ayarladıysanız {cache:false}jQuery otomatik olarak bir önbellek bozma ekleyecektir perde arkasındayken başka bir şey yapmanıza gerek kalmadan.
JakeGould

0

Uygulamaya bağlı olarak, Safari> Advanced> Web Inspector'ı kullanarak şimdi iOS 6'da sorunu çekmekte sorun yaşayabilirsiniz, böylece bu durumla yardımcı olur.

Telefonu Mac'te Safari'ye bağlayın ve ardından web uygulamasını çekmekte sorun yaşamak için geliştirici menüsünü kullanın.

Web Görünümü kullanan uygulamaya özgü de dahil olmak üzere iOS6'ya güncelleme yaptıktan sonra iPhone'daki web sitesi verilerini temizleyin. Sadece bir uygulamanın bir sorunu vardı ve bu IOS6 Beta testi sırasında bunu çözdü, o zamandan beri gerçek bir sorun yok.

Uygulamanıza da bakmanız, özel bir uygulamada bir WebView'daysanız NSURLCache'ye göz atmanız gerekebilir.

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

Sanırım probleminizin, doğanızın, vb. Gerçek doğasına bağlı ..

Ref: $ .ajax çağrıları


Bu, orijinal soruyu doğrudan ele almasa da, genel olarak cihazlardaki sorunları giderebilmeniz için çok yararlı bilgilerdir, bu yüzden oylama yapıyorum.
Kris Giesing

0

Neden işe yaradığını merak etmemi sağlayan bir çözüm buldum. Tadej'in ASP.NET web hizmeti ile ilgili cevabını okumadan önce, işe yarayacak bir şey bulmaya çalışıyordum.

Ve bunun iyi bir çözüm olduğunu söylemiyorum, ama sadece burada belgelemek istedim.

ana sayfa: bir JavaScript işlevi içerir, checkStatus (). Yöntem, html içeriğini güncellemek için jQuery AJAX çağrısı kullanan başka bir yöntemi çağırır. CheckStatus () öğesini çağırmak için setInterval kullandım. Tabii ki, önbellek sorunuyla karşılaştım.

Çözüm: güncellemeyi çağırmak için başka bir sayfa kullanın.

Ana sayfada, bir boole değişkeni, runUpdate ayarladım ve gövde etiketine aşağıdakileri ekledim:

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

Helper.html dosyasında:

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

Yani, ana sayfadan checkStatus () çağrılırsa, önbelleğe alınmış içeriği alıyorum. CheckStatus'u alt sayfadan ararsam, güncellenmiş içerik alırım.


0

Giriş ve kayıt sayfalarım Firefox, IE ve Chrome'da bir cazibe gibi çalışırken ... IOS ve OSX için Safari'de bu sorunla mücadele ediyorum, birkaç ay önce SO'da bir çözüm buldum.

<body onunload="">

VEYA javascript ile

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

Bu çirkin bir şey ama bir süre çalışıyor.

Nedenini bilmiyorum, ancak onunloadsayfanın Safari'de önbelleğe alınmadığı etkinliğe null döndürme .


0

İOS 9 ve 10 sürümlerini çalıştıran eski iPhone'ların ve iPad'lerin, belki de Apple'ın CPU hızını düşürmesi nedeniyle bazen sahte boş AJAX sonuçları döndürdüğünü bulduk. Boş sonucu döndürürken iOS, önbellekten bir sonuç döndürüyormuş gibi sunucuyu çağırmaz. Frekans, AJAX çağrılarının kabaca% 10'undan% 30'una boş olarak değişir.

Çözüme inanmak zor. Sadece 1 saniye bekleyin ve tekrar arayın. Testlerimizde, ihtiyaç duyulan tek bir tekrar vardı, ancak 4 kez aramak için kodu yazdık. 1'lerin beklemesinin gerekli olup olmadığından emin değiliz, ancak sunucumuzu tekrarlanan çağrıların patlamasıyla yük altına almak istemedik.

Sorunun, farklı verilerle farklı API dosyalarına çağrı yapan iki farklı AJAX çağrısında meydana geldiğini gördük. Ama herhangi bir AJAX çağrısında olabileceğinden endişeliyim. Bilmiyoruz çünkü her AJAX sonucunu incelemiyoruz ve her çağrıyı eski cihazlarda birçok kez test etmiyoruz.

Her iki sorun AJAX çağrısı kullanıyordu: POST, Asynchronously = true, setRequestHeader = ('Content-Type', 'application / x-www-form-urlencoded')

Sorun oluştuğunda, genellikle yalnızca bir AJAX çağrısı devam eder. Yani çakışan AJAX çağrılarından kaynaklanmıyor. Bazen sorun cihaz meşgulken olur, ancak bazen olmaz ve DevTools olmadan o anda ne olduğunu gerçekten bilmiyoruz.

iOS 13 bunu veya Chrome veya Firefox'u yapmaz. İOS 11 veya 12'yi çalıştıran herhangi bir test cihazımız yok. Belki de başka biri bunları test edebilir?

Bunu burada belirtiyorum çünkü bu soru, bu sorunu ararken en iyi Google sonucu.



-2

İşlev imzasını böyle bir şey olarak değiştirmek için bir geçici çözüm öneririm:

getNewRecordID (intRecordType, strTimestamp) ve sonra da her zaman bir TimeStamp parametresi de iletin ve bu değeri sunucu tarafında atın. Bu sorunu giderir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.