Caching tak terduga dari hasil AJAX di IE8

135

Saya mengalami masalah serius dengan hasil cache Internet Explorer dari permintaan JQuery Ajax.

Saya memiliki header di halaman web saya yang diperbarui setiap kali pengguna menavigasi ke halaman baru. Setelah halaman dimuat saya melakukan ini

$.get("/game/getpuzzleinfo", null, function(data, status) {
    var content = "<h1>Wikipedia Maze</h1>";
    content += "<p class='endtopic'>Looking for <span><a title='Opens the topic you are looking for in a separate tab or window' href='" + data.EndTopicUrl + "' target='_blank'>" + data.EndTopic + "<a/></span></p>";
    content += "<p class='step'>Step <span>" + data.StepCount + "</span></p>";
    content += "<p class='level'>Level <span>" + data.PuzzleLevel.toString() + "</span></p>";
    content += "<p class='startover'><a href='/game/start/" + data.PuzzleId.toString() + "'>Start Over</a></p>";

    $("#wikiheader").append(content);

}, "json");

Itu hanya menyuntikkan info header ke halaman. Anda dapat memeriksanya dengan membuka www.wikipediamaze.com lalu masuk dan memulai teka-teki baru.

Di setiap browser yang saya uji (Google Chrome, Firefox, Safari, Internet Explorer), ini berfungsi dengan baik kecuali di IE. Semuanya diinjeksi dengan baik di IE pertama kali, tetapi setelah itu bahkan tidak pernah membuat panggilan ke /game/getpuzzleinfo. Ini seperti telah menyimpan hasil atau sesuatu.

Jika saya mengubah panggilan ke $.post("/game/getpuzzleinfo", ...IE mengambilnya dengan baik. Tapi kemudian Firefox berhenti berfungsi.

Bisakah seseorang menjelaskan hal ini tentang mengapa IE melakukan cache $.getpanggilan ajax saya ?

MEMPERBARUI

Sesuai saran di bawah ini, saya telah mengubah permintaan ajax saya menjadi ini, yang memperbaiki masalah saya:

$.ajax({
    type: "GET",
    url: "/game/getpuzzleinfo",
    dataType: "json",
    cache: false,
    success: function(data) { ... }
});
Mikha
sumber
8
Terima kasih telah menanyakan ini. Saya tidak bisa berkata-kata bahwa perilaku browser ini.
john
1
Pertanyaan bagus, dan situs web yang sangat keren. Ide bagus.
MikeMurko

Jawaban:

177

IE terkenal karena caching agresif dari respons Ajax. Saat Anda menggunakan jQuery, Anda dapat mengatur opsi global:

$.ajaxSetup({
    cache: false
});

yang akan menyebabkan jQuery menambahkan nilai acak ke string kueri permintaan, sehingga mencegah IE menyimpan respons.

Perhatikan bahwa jika Anda memiliki panggilan Ajax lain yang terjadi di mana Anda ingin menyimpan cache, ini juga akan menonaktifkannya untuk mereka. Dalam kasus tersebut, alihkan untuk menggunakan metode $ .ajax () dan aktifkan opsi itu secara eksplisit untuk permintaan yang diperlukan.

Lihat http://docs.jquery.com/Ajax/jQuery.ajaxSetup untuk info lebih lanjut.

NickFitz
sumber
1
Anda juga dapat menambahkan stempel waktu di akhir url Anda. Tidak yakin mengapa jQuery tidak menggunakan pendekatan ini.
Eric Johnson
14
@Eric: itulah yang dilakukan jQuery secara internal - opsi "cache: false" hanya memerintahkannya untuk melakukan itu.
NickFitz
Mengapa jquery tidak mengaktifkan ini secara default?
speedplane
Saya baru tahu bahwa opsi cache tidak berfungsi saat Anda mencoba meminta beranda di IE 8, dengan panggilan ke /. Ubah ke /index.phpatau apa pun url lengkapnya. Atau tambahkan beberapa /?f=f
param
8

Seperti yang disebutkan di marr75 , GETs di-cache.

Ada beberapa cara untuk mengatasi ini. Selain mengubah header respons, Anda juga dapat menambahkan variabel string kueri yang dibuat secara acak ke akhir URL yang ditargetkan. Dengan cara ini, IE akan menganggapnya sebagai URL yang berbeda setiap kali diminta.

Ada beberapa cara untuk melakukan ini (seperti menggunakan Math.random(), variasi tanggal, dll).

Inilah salah satu cara Anda dapat melakukannya:

var oDate = new Date();
var sURL = "/game/getpuzzleinfo?randomSeed=" + oDate.getMilliseconds();
$.get(sURL, null, function(data, status) {
    // your work
});
Tom
sumber
3

Gets selalu dapat disimpan dalam cache. Salah satu strategi yang mungkin berhasil adalah mengedit header respons dan memberi tahu klien untuk tidak menyimpan informasi dalam cache atau segera menghentikan cache.

marr75
sumber
Kedengarannya ide yang bagus. Bagaimana saya akan melakukan itu?
Mikha
1
Itu pertanyaan yang dimuat, tergantung pada kode sisi server Anda. Lihat entri wikipedia "Daftar tajuk HTTP" untuk sedikit panduan. Contoh: Kontrol-Cache: tanpa-cache Kedaluwarsa: Kam, 01 Des 1994 16:00:00 GMT Pada dasarnya Anda perlu menambahkan header tanggapan ini ke tanggapan http Anda. Ini cukup sederhana di ASP.NET, Ruby, dan PHP. Cukup cari bahasa sisi server yang Anda gunakan + ubah header respons.
marr75
3
Juga, dan ini sama sekali bukan kritik terhadap Jquery (Saya suka pustaka itu), metode menambahkan parameter string kueri acak aman tetapi tidak sopan bagi klien (dapat membuat mereka memegang item dalam cache yang tidak akan pernah digunakan lagi).
marr75
2

Jika Anda memanggil halaman ashx, Anda juga dapat menonaktifkan caching di server dengan kode berikut:

context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
context.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches); 
Andrej Benedik
sumber
1

inilah yang saya lakukan untuk panggilan ajax:

var url = "/mypage.aspx";
// my other vars i want to add go here
url = url + "&sid=" + Math.random();
// make ajax call

itu bekerja dengan cukup baik untuk saya.

Jason
sumber
1

NickFitz memberikan jawaban yang bagus, tetapi Anda juga harus mematikan caching di IE9. Untuk menargetkan hanya IE8 dan IE9, Anda dapat melakukan ini;

<!--[if lte IE 9]>
<script>
    $.ajaxSetup({
        cache: false
    });
</script>
<![endif]-->
Stuart Hallows
sumber
0

Jawaban di sini sangat membantu bagi mereka yang menggunakan jQuery atau karena alasan tertentu langsung menggunakan objek xmlHttpRequest ...

Jika Anda menggunakan proxy layanan Microsoft yang dibuat secara otomatis, ini tidak mudah untuk dipecahkan.

Triknya adalah dengan menggunakan metode Sys.Net.WebRequestManager.add_invokingRequest di event handler, ubah url permintaan:

networkRequestEventArgs._webRequest._url = networkRequestEventArgs._webRequest._url + '&nocache=' + new Date().getMilliseconds(); 

Saya telah membuat blog tentang ini: http://yoavniran.wordpress.com/2010/04/27/ie-caching-ajax-results-how-to-fix/

poeticGeek
sumber
0

Baru saja menulis blog tentang masalah ini hanya menggunakan ExtJS ( http://thecodeabode.blogspot.com/2010/10/cache-busting-ajax-requests-in-ie.html )

Masalahnya adalah karena saya menggunakan format penulisan ulang url tertentu, saya tidak dapat menggunakan parameter string kueri konvensional (? Param = value), jadi saya menulis parameter penghilang cache sebagai variabel yang diposting ..... Saya akan berpikir bahwa menggunakan variabel POST sedikit lebih aman daripada GET, hanya karena banyak kerangka kerja MVC menggunakan pola tersebut

protokol: // host / controller / action / param1 / param2

dan pemetaan nama variabel ke nilai hilang, dan parameter hanya ditumpuk ... jadi saat menggunakan parameter perusak cache GET

yaitu protokol: // host / controller / action / param1 / param2 / no_cache122300201

no_cache122300201 dapat disalahartikan sebagai parameter $ param3 yang dapat memiliki nilai default

yaitu

tindakan fungsi publik ($ param1, $ param2, $ param3 = "nilai default") {//..//}

tidak ada kemungkinan hal itu terjadi dengan POSTED cache busters

Ben
sumber
0

Jika Anda menggunakan ASP.NET MVC, itu cukup untuk menambahkan baris ini di atas tindakan pengontrol:

[OutputCache(NoStore=true, Duration = 0, VaryByParam = "None")]
public ActionResult getSomething()
{

}
Emil
sumber
Perilaku yang dimaksud ada di sisi browser; jawaban ini berkaitan dengan caching di sisi server.
Mark Sowul
@MarkSowul Outputcache memiliki 3 pilihan Client, Server dan any. IE menggunakan OutputCache sebagai default semua yang sebagian besar berjalan sebagai cache sisi Klien. Anda dapat melihat detail lebih lanjut di sini dougwilsonsa.wordpress.com/2011/04/29/…
Emil
@MarkSowul Anda juga dapat melihat pertanyaan dan jawaban terkait di sini. Apakah menurut Anda ini juga di sisi server? stackoverflow.com/questions/2653092/…
Emil
1
Ya, maaf, Anda benar sedang - aku tidak menyadari bahwa jawaban Anda dapat mempengaruhi kedua cache server-side dan cache sisi klien.
Mark Sowul
-1

IE berhak melakukan caching ini; untuk memastikan item tidak di-cache, header harus disetel dengan sesuai.

Jika Anda menggunakan ASP.NET MVC, Anda dapat menulis ActionFilter; masuk OnResultExecuted, periksafilterContext.HttpContext.Request.IsAjaxRequest() . Jika demikian, setel header respons yang kedaluwarsa:filterContext.HttpContext.Response.Expires = -1;

Sesuai http://www.dashbay.com/2011/05/internet-explorer-caches-ajax/ :

Beberapa orang lebih suka menggunakan header Cache - Control: no - cache daripada kadaluarsa. Inilah perbedaannya:
Cache-Control: no-cache - benar-benar NO caching
Kedaluwarsa: -1 - browser “biasanya” menghubungi server Web untuk update halaman tersebut melalui permintaan bersyarat If-Modified-Because. Namun, halaman tetap berada di cache disk dan digunakan dalam situasi yang sesuai tanpa menghubungi server Web jarak jauh, seperti saat tombol KEMBALI dan MAJU digunakan untuk mengakses riwayat navigasi atau saat browser dalam mode luring.

Mark Sowul
sumber