AJAX çağrı sonucunun tarayıcı önbelleğe alınmasını önleme


262

Kullanarak dinamik içerik $.get()yüklersem sonuç tarayıcıda önbelleğe alınır.

QueryString'e rastgele bir dize eklemek bu sorunu çözüyor gibi görünüyor (kullanıyorum new Date().toString()), ancak bu bir hack gibi geliyor.

Bunu başarmanın başka bir yolu var mı? Veya, benzersiz dize bunu başarmak için tek yol, başka herhangi bir öneri ise new Date()?


Kısa gösterimi $.now(), her seferinde (yeni bir Date (). GetTime ()) yapmak yerine kullanabilirsiniz .
Dayson

1
Soru başlığınız biraz yanıltıcı. Yeniden adlandırmayı düşünebilir misiniz?
0112

4
Kabul edilen cevap olarak başka bir cevap seçmeyi düşündünüz mü?
M4N

Yanıtlar:


241

Kullandığım new Date().getTime()Aynı milisaniye içinde gerçekleşen birden çok istek yoksa çakışmaları önlemek edecek olan:

$.get('/getdata?_=' + new Date().getTime(), function(data) {
    console.log(data); 
});

Edit: Bu cevap birkaç yaşında. Hala çalışıyor (bu yüzden silmedim), ancak şimdi bunu başarmanın daha iyi / temiz yolları var . Benim tercihim bu yöntem için, ancak bu yanıt, bir sayfanın ömrü boyunca her istek için önbelleğe almayı devre dışı bırakmak istiyorsanız da yararlıdır .


11
Sadece jQuery'nin Peter J'nin cevabındaki gibi bunu yapmasına izin vermek daha temiz olacağı için çözümün işe yarayacak, ancak uzun vadede bakımı daha zor olacak.
Niklas Wulff

11
Bunun hangi kısmı bakım gerektiriyor? JQuery ne ile karşılaştırıldığında?
Güneşli R Gupta

5
O söz etmek anlamlı olabilir new Date().getTime()... kodu şöyle kullanılır var nocache = new Date().getTime(); var path = 'http://hostname.domain.tld/api/somejsonapi/?cache=' + nocache;. Bunu bulmam birkaç dakika sürdü, kendim. Tabii ki ?cacheAPI'nın gerçekten istemediği herhangi bir ifade olabilir.
doubleJ

1
Peter J'in cevabı daha iyi bir yaklaşıma sahip olsa bile bu cevap yanlış veya kötü bir cevap değildir. DV'nin yapıldığına inanıyorum çünkü seninki Peter'ın üstünde (kabul edildiği gibi). ve OP 2013 başından beri
Michel Ayres

1
url = url + (-1 === url.indexOf('?') ? '?' : '&') + "__=" + Number(new Date());

514

Aşağıdakiler, hangi jQuery yöntemini kullanırsanız kullanın ($ .get, $ .ajax, vb.) Gelecekteki tüm AJAX isteklerinin önbelleğe alınmasını önleyecektir.

$.ajaxSetup({ cache: false });

7
Soruşturma üzerine (Fiddler), jQuery bunu sadece bir zaman damgası ekleyerek dahili olarak uygulamaktadır (bu cevaplarda başka yerlerde tartışıldığı gibi). Bana göre .ajaxSetup yöntemi daha temiz (bence.)
Peter J

8
Gerçekten de belge hazır çağrısının içinde olması gerekmez.
Peter J

19
Ajax önbelleğini global olarak neden devre dışı bırakmalıyım? Bence bu, Jonathan'ın cevabının yaptığı gibi, çağrı başına yapılmalı.
Sunny R Gupta

5
Uygulamanız için ne işe yararsa. Tüm AJAX çağrıları için kesinlikle taze verilere ihtiyaç duyduğumda bu yöntemi ticari uygulamalarda kullanmaya devam ediyorum. Diğerleri için önbelleğe alınmış veriler uygundur.
Peter J

1
bağlantı Açıklama: Gelecekteki Ajax istekleri için varsayılan değerleri ayarlayın. Kullanımı tavsiye edilmez.
itwebdeveloper

319

JQuery'nin $ .get () sonuçları önbelleğe alınır. Onun yerine

$.get("myurl", myCallback)

önbelleği kapatmanıza izin veren $ .ajax kullanmalısınız:

$.ajax({url: "myurl", success: myCallback, cache: false});

62
+1 Bu doğru cevap. Peter J'nin önbelleğe almayı küresel olarak devre dışı bırakma çözümü, IMO'nun kötü bir uygulamadır.
Salman von Abbas

7
Sayfa / istek için yalnızca "global" olduğunu belirtmek önemlidir.
Peter J

3
+1: Önbelleğe alma, istek türüne özgü olmalıdır. Bazı sunucu isteklerinin önbelleğe alınması gerekebilir (sunucu verilerinin statik olduğu yerlerde), bu nedenle istek temelinde önbelleğe almayı seçmek yalnızca hepsini kapatmaktan daha iyidir .
Gitti Kodlama

1
Doğru yanıt için +1 - manuel bir kesmek yerine jQuery yöntemini kullanarak arama başına önbelleğe almayı önleme.
Brendan Hill

2
Başka bir iyi cevap. Benim için, küresel önbelleği devre dışı bırakmanın çoğu zaman büyük fayda sağladığını söylemeliyim. Her şey uygulamanızın nasıl tasarlandığına bağlıdır. Gümüş mermi yok, ancak bu durumda, önbellekleme için bir boole, geri arama işlevi ve modülerlik için URL'yi kabul eden bir işlev öneriyorum. El ile "hack" gayet iyi, ancak jQuery kullanıyorsanız, mümkün olduğunca işlevlerine bağlı kalın. Bu artık sadece gelişimi kolaylaştırmakla kalmayacak, aynı zamanda gelecekteki kütüphaneye de yükseltilecek.
Anthony Mason

24

Buradaki tüm yanıtlar, sunucunun erişim günlüklerinde görünecek olan istenen URL'ye ayak izi bırakıyor.

Hiçbir yan etkisi olmayan başlık tabanlı bir çözüme ihtiyacım vardı ve tüm tarayıcılarda Web sayfası önbelleğini nasıl kontrol edebilirim? .

En azından Chrome için çalışan sonuç şöyle olur:

$.ajax({
   url: url, 
   headers: {
     'Cache-Control': 'no-cache, no-store, must-revalidate', 
     'Pragma': 'no-cache', 
     'Expires': '0'
   }
});


Belki aptalca bir soru, ama ajax'ım görüntüleri döndürürse, görüntüler önbelleğe alınır mı? Büyük Amazon S3 isteklerinden kaçınmak için?
Marcelo Agimóvel

MarceloAgimóvel, bu ayrı bir SO soru olabilir inanıyorum.
Aidin

23

başka bir yol, ajax çağrısına yanıt oluşturan kodda sunucu tarafında hiçbir önbellek başlığı vermemektir:

response.setHeader( "Pragma", "no-cache" );
response.setHeader( "Cache-Control", "no-cache" );
response.setDateHeader( "Expires", 0 );

17
Yanlış. IE'de, burada açıklandığı gibi XMLHttpRequest çağrıları için önbelleksiz başlıklar yoksayılır: stackoverflow.com/questions/244918/… DateTime (veya benim .ajaxSetup yöntemim) gerçekten çalışan tek çözümlerdir.
Peter J

Ben sadece benim her zamanki önbellek mantra yapıştırılan, IE özgü olduğu belirtilmedi
miceuz

2
Bu, tüm tarayıcılar için önbelleği kapatmalıdır: response.setHeader ("Cache-Control", "max-age = 0, önbellek yok, mağaza yok, post-check = 0, pre-check = 0");
Chris Broski

13

Şahsen, sorgu dizesi yönteminin sunucuda üstbilgileri ayarlamaya çalışmaktan daha güvenilir olduğunu hissediyorum - bir proxy veya tarayıcının yine de önbelleğe almayacağının garantisi yoktur (bazı tarayıcılar diğerlerinden daha kötüdür - isim vermeden).

Genellikle kullanıyorum Math.random()ama tarih kullanarak yanlış bir şey görmüyorum (AJAX isteklerini aynı değeri iki kez almak için yeterince hızlı yapmamalısınız).


2
Date (). GetTime () öğesini Math.random () ile birleştirin ve güvenli tarafta olmalısınız. Yan notta Ext.Ajax, copyCaching belirtildiğinde getTime () öğesini de kullanır.
vividos

12

Belgeleri takip ederek: http://api.jquery.com/jquery.ajax/

cacheözelliği aşağıdakilerle birlikte kullanabilirsiniz :

$.ajax({
    method: "GET",
    url: "/Home/AddProduct?",
    data: { param1: value1, param2: value2},
    cache: false,
    success: function (result) {
        // TODO
    }
});

5

Tabii ki "önbellek kırma" teknikleri işi halledecektir, ancak sunucu istemciye yanıtın önbelleğe alınmaması gerektiğini belirtmişse bu ilk sırada olmaz. Bazı durumlarda, yanıtları önbelleğe almak yararlı olur, bazen değil. Verilerin doğru kullanım ömrüne sunucunun karar vermesine izin verin. Daha sonra değiştirmek isteyebilirsiniz. UI kodunuzdaki birçok farklı yerden sunucudan yapmak çok daha kolay.

Tabii ki sunucu üzerinde kontrolünüz yoksa bu yardımcı olmaz.


5

GET yerine POST isteği kullanmaya ne dersiniz? (Yine de yapmalısın ...)


Bence bu daha iyi bir çözüm, ama ne yazık ki (bir şekilde) sadece GET isteği yapabilirim. Yani .. şimdilik yeni Date (). GetTime ().
Salamander2007

Lütfen yanıtınıza başkalarının ondan öğrenebilecekleri bir açıklama ekleyin - POST isteğine neden ihtiyaç duyulmalıdır?
Nico Haase

5

Asıl soru, bunun önbelleğe alınmaması için neden ihtiyacınız olduğu. Her zaman değiştiği için önbelleğe alınmaması gerekiyorsa, sunucu kaynağı önbelleğe almamayı belirtmelidir. Sadece bazen değişirse (bağlı olduğu kaynaklardan biri değişebilir) ve istemci kodu bunu bilmenin bir yolu varsa, bazı karma veya son değiştirilme tarihinden hesaplanan URL'ye kukla bir parametre ekleyebilir (Microsoft Ajax komut dosyası kaynaklarında bunu yaparız, böylece sonsuza kadar önbelleklenebilirler, ancak yeni sürümler göründükleri gibi sunulabilirler). İstemci değişiklikleri bilmiyorsa, sunucunun HEAD isteklerini doğru bir şekilde işlemesi ve istemciye önbelleğe alınmış sürümü kullanıp kullanmamasını söylemesinin doğru yolu olmalıdır. Bana rasgele bir parametre eklemek veya istemciden hiçbir zaman önbelleğe almalarını söylememek yanlış görünüyor çünkü önbelleğe alınabilirlik sunucu kaynağının bir özelliğidir ve bu yüzden sunucu tarafında karar verilmelidir. Kendisine sorulması gereken bir başka soru, bu kaynağın gerçekten GET aracılığıyla sunulması mı yoksa POST'tan geçmesi mi? Bu bir anlambilim meselesidir, ancak güvenlikle ilgili etkileri de vardır (yalnızca sunucu GET'in izin verdiği durumlarda çalışan saldırılar vardır). POST önbelleğe alınmayacak.


6
Önbellek ilkelerini denetlemediğiniz proxy sunucularından geçiyorsanız ne olur? uygulamanızın her seferinde açıkça yeni bir istekte bulunması gerekiyorsa ne olur? Şeylerin cevabı her zaman net siyah ve beyaz kesilmez, her zaman gri alanlar vardır.
7wp

Doğru, her zaman net bir kesim değil. Ama bu cevabı görmek varsayımlarımı sorgulamama ve problemimin temel nedenini bulmama neden oldu. Bu herkes için geçerli olmayabilir, ama bana yardımcı oldu. Eğer burada okuyorsanız, bunu da düşünmelisiniz.
Jonathan Tran

Bu bana yardımcı oldu, ResponseCaching varsayılan olarak 60m sunucu tarafına ayarlandı. Önbellek Yok olarak değiştirildi ve istemcide önbelleğe almayı durdurdu.
mattygee

4

Belki de bunun yerine $ .ajax () 'a bakmalısınız (eğer jQuery kullanıyorsanız, benziyor). Şuna bir göz atın: http://docs.jquery.com/Ajax/jQuery.ajax#options ve "önbellek" seçeneği.

Başka bir yaklaşım, sunucu tarafında işleri nasıl önbelleğe aldığınıza bakmak olacaktır.


1
Ne yazık ki, bazı araştırmalardan sonra, $ .ajax () ve set cache = false kullanmak temel olarak aynı şeyi yapacaktır. jQuery sorgu dizesine rastgele bir sayı ekler ve mevcut sorgu dizesini kontrol etmez. Bu yüzden $ .get () kullanmak yeterli olacaktır.
Salamander2007

Ah tamam. Hiç denemedim, dokümanlarda bu konuda bir şeyler gördüğümü hatırladım :)
finpingvin

$ .Ajax kullanmak bile gerekli değildir. Basitçe .ajaxSetup kullanın.
Peter J

3

Verilen mükemmel cevaplara küçük bir ek: Javascript olmayan kullanıcılar için ajax olmayan bir yedekleme çözümü ile çalışıyorsanız, bu sunucu tarafı başlıklarını yine de doğru yapmanız gerekir. Vazgeçenleri anlasam da bu imkansız değil;)

Eminim SO size uygun başlıkların tamamını verecek başka bir soru var. Ben tamamen mahkum değil fareler cevap tüm üsleri% 100 kapsar.


3

Mobil Safari'de cacheseçeneğini kullananlarınız için $.ajaxSetup(), mobil Safari de önbelleğe aldığı için POST'lar için bir zaman damgası kullanmanız gerekebilir. $.ajax()( Üzerinden yönlendirildiğiniz $.ajaxSetup()) belgelerine göre :

Önbelleği false olarak ayarlamak, yalnızca HEAD ve GET istekleriyle doğru şekilde çalışır. GET parametrelerine "_ = {timestamp}" ekleyerek çalışır. Parametre, bir GET tarafından önceden talep edilen bir URL'ye POST yapıldığında IE8 dışında, diğer istek türleri için gerekli değildir.

Dolayısıyla, bu seçeneği tek başına ayarlamak, yukarıda bahsettiğim durumda size yardımcı olmaz.


2

Temel cache:false;olarak, ilerledikçe içeriğin değişeceğini düşündüğünüz ajax'ı ekleyin . Ve içeriğin değişmeyeceği yer u bunu atlayabilir. Bu şekilde her seferinde yeni yanıt alacaksınız


2

Internet Explorer'ın Ajax Caching: Bu konuda ne yapacaksınız? üç yaklaşım önerir:

  1. Sorgu dizesine? Date = [timestamp] gibi bir önbellek bozma belirteci ekleyin. JQuery ve YUI'de bunu otomatik olarak yapmalarını söyleyebilirsiniz.
  2. GET yerine POST kullanma
  3. Tarayıcıları önbelleğe almasını özellikle yasaklayan bir HTTP yanıt başlığı gönderin

2

Şimdi, ajax isteğinizde önbellek seçeneğini etkinleştirerek / devre dışı bırakarak bunu yapmak kolaydır, tıpkı bunun gibi

$(function () {
    var url = 'your url goes here';
    $('#ajaxButton').click(function (e) {
        $.ajax({
            url: url,
            data: {
                test: 'value'
            },
                cache: true, //cache enabled, false to reverse
                complete: doSomething
            });
        });
    });
    //ToDo after ajax call finishes
    function doSomething(data) {
        console.log(data);
    }
});

3
6 yıl sonra Jonathan ile aynı cevabı veriyorsunuz? ಠ_ಠ
redent84

insanlar soru gönderildikten 6 yıl sonra olduğunu söyleyebilir. Ve bu soruya cevabım diğerlerinden farklı, bugünlerde doğru olandan bahsetmiyorum bile. Bu tür soruları yanıtlamak topluluk ve yeni başlayanlar için "asker" değildir! Yine de açıklamayı eklediğiniz için teşekkürler!
Omar El Don

Sizinkiyle bu arasındaki fark nedir stackoverflow.com/a/735084/469218 ?
redent84

belki de böyle bir soru soran bir acemi açısından netliktir !!
Omar El Don


1

@Athasach'ın dediği gibi, jQuery belgelerine göre, $.ajaxSetup({cache:false}) GET ve HEAD istekleri dışında çalışmayacaktır.

Bir geri göndermeniz daha iyi Cache-Control: no-cacheYine de üstbilgiyi sunucunuzdan . Endişelerin daha net bir şekilde ayrılmasını sağlar.

Tabii ki, bu projenize ait olmadığınız servis URL'leri için işe yaramaz. Bu durumda, üçüncü taraf hizmetini istemci kodundan çağırmak yerine sunucu kodundan proxy yapmayı düşünebilirsiniz.


1

.Net ASP MVC kullanıyorsanız, bitiş noktası işlevine aşağıdaki özniteliği ekleyerek denetleyici eylemindeki önbelleği devre dışı bırakın:

[OutputCacheAttribute(VaryByParam = "*", Duration = 0, NoStore = true)]

Bunu daha fazla açıklayabilir misiniz? Bu dizi AJAX ile nasıl ilişkilidir?
Nico Haase

Bu bir dizi değil, MVC Denetleyici Eyleminde bir özniteliğidir .
Marius

0

başlık ekle

headers: {
                'Cache-Control':'no-cache'
            }

Lütfen cevabınıza başkalarının ondan öğrenebilecekleri bir açıklama ekleyin - bu başlıklar nereye eklenmelidir?
Nico Haase

-3

eklemek Math.random() istek URL'ye


2
Bu kararsız sonuçlar verecektir.
aj.toulan

Math.random sadece url? _ = [Math.Random ()] gibi bir ölçüt görevi görür, kararsız sonuçla ilgisi yoktur.
xiaoyifang

4
Ne yaptığını anlıyorum. Sadece Math.Random () 'un bazen aynı sayıyı iki kez vereceğini söylüyordum. Sisteminizi belirsizlikler ile doldurursanız, bunlar yalnızca birbirinin üzerine eklenir.
aj.toulan
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.