การแคช AJAX ที่ไม่คาดคิดส่งผลให้ IE8


135

ฉันมีปัญหาร้ายแรงกับผลลัพธ์การแคชของ Internet Explorer จากคำขอ JQuery Ajax

ฉันมีส่วนหัวในหน้าเว็บของฉันที่ได้รับการอัปเดตทุกครั้งที่ผู้ใช้ไปที่หน้าใหม่ เมื่อโหลดหน้าเสร็จแล้วก็ทำเช่นนี้

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

เพียงแค่ฉีดข้อมูลส่วนหัวลงในหน้า คุณสามารถตรวจสอบได้โดยไปที่www.wikipediamaze.comจากนั้นเข้าสู่ระบบและเริ่มไขปริศนาใหม่

ในทุกเบราว์เซอร์ที่ฉันทดสอบ (Google Chrome, Firefox, Safari, Internet Explorer) มันใช้งานได้ดียกเว้นใน IE Eveything ได้รับการฉีดได้ดีใน IE ในครั้งแรกแต่หลังจากนั้นก็ไม่เคยโทรไป/game/getpuzzleinfoเลย มันเหมือนกับว่ามันเก็บผลลัพธ์หรืออะไรบางอย่างไว้

ถ้าฉันเปลี่ยนการโทรเป็น$.post("/game/getpuzzleinfo", ...IE ก็รับมันได้ดี แต่แล้ว Firefox ก็หยุดทำงาน

ใครช่วยให้ความกระจ่างเกี่ยวกับเรื่องนี้ได้บ้างว่าเหตุใด IE จึงแคชการ$.getโทร ajax ของฉัน

อัปเดต

ตามคำแนะนำด้านล่างฉันได้เปลี่ยนคำขอ ajax เป็นสิ่งนี้ซึ่งแก้ไขปัญหาของฉันได้:

$.ajax({
    type: "GET",
    url: "/game/getpuzzleinfo",
    dataType: "json",
    cache: false,
    success: function(data) { ... }
});

8
ขอบคุณที่ถามสิ่งนี้ ฉันพูดไม่ออกว่าพฤติกรรมของเบราว์เซอร์นี้
jjohn

1
คำถามที่ดีและเว็บไซต์ที่ยอดเยี่ยมจริงๆ ความคิดที่ดี.
MikeMurko

คำตอบ:


177

IE มีชื่อเสียงในด้านการแคชการตอบสนองของ Ajax ในเชิงรุก ในขณะที่คุณใช้ jQuery คุณสามารถตั้งค่าตัวเลือกส่วนกลาง:

$.ajaxSetup({
    cache: false
});

ซึ่งจะทำให้ jQuery เพิ่มค่าแบบสุ่มให้กับสตริงเคียวรีคำขอดังนั้นจึงป้องกันไม่ให้ IE แคชการตอบกลับ

โปรดทราบว่าหากคุณมีการโทร Ajax อื่น ๆ ที่คุณต้องการแคชสิ่งนี้จะปิดการใช้งานสำหรับผู้นั้นด้วย ในกรณีนั้นให้เปลี่ยนไปใช้เมธอด $ .ajax () และเปิดใช้งานตัวเลือกนั้นอย่างชัดเจนสำหรับคำขอที่จำเป็น

ดูhttp://docs.jquery.com/Ajax/jQuery.ajaxSetupสำหรับข้อมูลเพิ่มเติม


1
คุณยังสามารถเพิ่มการประทับเวลาต่อท้าย URL ของคุณได้อีกด้วย ไม่แน่ใจว่าทำไม jQuery ถึงไม่ใช้แนวทางนี้แทน
Eric Johnson

14
@Eric: นั่นคือสิ่งที่ jQuery ทำภายใน - ตัวเลือก "cache: false" เพียงแค่บอกให้ทำเช่นนั้น
NickFitz

เหตุใด jquery จึงไม่เปิดใช้โดยค่าเริ่มต้น
เครื่องบินเร็ว

ผมเพิ่งสังเกตเห็นว่าตัวเลือกแคชไม่ทำงานเมื่อคุณพยายามที่จะขอหน้าแรกใน IE 8 /ด้วยการเรียกร้องให้ เปลี่ยน/index.phpเป็น URL แบบเต็มหรืออะไรก็ได้ หรือเพิ่ม/?f=f
พารามิเตอร์

8

ตามที่กล่าวถึงmarr75GETจะถูกแคช

มีสองวิธีในการต่อสู้กับปัญหานี้ นอกเหนือจากการแก้ไขส่วนหัวการตอบกลับแล้วคุณยังสามารถต่อท้ายตัวแปรสตริงการสืบค้นที่สร้างแบบสุ่มต่อท้าย URL เป้าหมายได้อีกด้วย วิธีนี้ IE จะคิดว่าเป็น URL ที่แตกต่างกันทุกครั้งที่มีการร้องขอ

มีหลายวิธีในการดำเนินการนี้ (เช่นการใช้Math.random()รูปแบบของวันที่ ฯลฯ )

นี่คือวิธีหนึ่งที่คุณสามารถทำได้:

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

3

Gets สามารถแคชได้เสมอ กลยุทธ์อย่างหนึ่งที่อาจได้ผลคือการแก้ไขส่วนหัวการตอบกลับและแจ้งให้ลูกค้าทราบว่าอย่าแคชข้อมูลหรือให้แคชหมดอายุในไม่ช้า


ฟังดูเหมือนเป็นความคิดที่ดี ฉันจะทำอย่างนั้นได้อย่างไร?
คาห์

1
นั่นเป็นคำถามที่โหลดขึ้นอยู่กับรหัสฝั่งเซิร์ฟเวอร์ของคุณ ดูรายการวิกิพีเดีย "รายการส่วนหัว HTTP" สำหรับคำแนะนำเล็กน้อย ตัวอย่าง: Cache-Control: no-cache Expires: Thu, 01 Dec 1994 16:00:00 GMT โดยทั่วไปคุณต้องผนวกส่วนหัวการตอบกลับเหล่านี้เข้ากับการตอบกลับ http ของคุณ มันค่อนข้างง่ายใน ASP.NET, Ruby และ PHP เพียงแค่ค้นหาภาษาฝั่งเซิร์ฟเวอร์ที่คุณใช้ + แก้ไขส่วนหัวการตอบกลับ
มี.ค. 75

3
นอกจากนี้และนี่ไม่ใช่คำวิจารณ์ของ Jquery เลย (ฉันชอบไลบรารีนั้น) วิธีการเพิ่มพารามิเตอร์สตริงการสืบค้นแบบสุ่มนั้นปลอดภัย แต่ไม่สุภาพต่อไคลเอนต์ (สามารถปล่อยให้พวกเขาถือรายการในแคชที่จะไม่ถูกใช้ อีกครั้ง).
มี.ค. 75

2

หากคุณกำลังเรียกใช้เพจ ashx คุณสามารถปิดใช้งานการแคชบนเซิร์ฟเวอร์ด้วยรหัสต่อไปนี้:

context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
context.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches); 

1

นี่คือสิ่งที่ฉันทำเพื่อการโทรของ ajax:

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

มันทำงานได้ดีสำหรับฉัน


1

NickFitz ให้คำตอบที่ดี แต่คุณจะต้องปิดการแคชใน IE9 ด้วย เพื่อกำหนดเป้าหมายเฉพาะ IE8 และ IE9 คุณสามารถทำได้

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

0

คำตอบที่นี่มีประโยชน์มากสำหรับผู้ที่ใช้ jQuery หรือด้วยเหตุผลบางประการใช้วัตถุ xmlHttpRequest โดยตรง ...

หากคุณใช้พร็อกซีบริการของ Microsoft ที่สร้างขึ้นโดยอัตโนมัติการแก้ปัญหานั้นไม่ง่ายอย่างที่คิด

เคล็ดลับคือการใช้เมธอด Sys.Net.WebRequestManager.add_invokingRequest ในตัวจัดการเหตุการณ์เปลี่ยน url คำขอ:

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

ฉันเขียนบล็อกเกี่ยวกับเรื่องนี้: http://yoavniran.wordpress.com/2010/04/27/ie-caching-ajax-results-how-to-fix/


0

เพิ่งเขียนบล็อกเกี่ยวกับปัญหานี้โดยใช้ ExtJS เท่านั้น ( http://thecodeabode.blogspot.com/2010/10/cache-busting-ajax-requests-in-ie.html )

ปัญหาคือเมื่อฉันใช้รูปแบบการเขียน URL ใหม่โดยเฉพาะฉันไม่สามารถใช้พารามิเตอร์สตริงการสืบค้นแบบเดิมได้ (? param = value) ดังนั้นฉันจึงเขียนพารามิเตอร์การป้องกันแคชเป็นตัวแปรที่โพสต์แทน ..... ฉันคิดว่า การใช้ตัวแปร POST นั้นปลอดภัยกว่า GET เล็กน้อยเพียงเพราะเฟรมเวิร์ก MVC จำนวนมากใช้รูปแบบ

โปรโตคอล: // host / controller / action / param1 / param2

ดังนั้นการแมปชื่อตัวแปรกับค่าจึงหายไปและพารามิเตอร์จะถูกซ้อนกัน ... ดังนั้นเมื่อใช้พารามิเตอร์ GET cache buster

เช่นโปรโตคอล: // host / controller / action / param1 / param2 / no_cache122300201

no_cache122300201 สามารถเข้าใจผิดว่าเป็นพารามิเตอร์ $ param3 ซึ่งอาจมีค่าดีฟอลต์

กล่าวคือ

การทำงานของฟังก์ชันสาธารณะ ($ param1, $ param2, $ param3 = "default value") {//..//}

ไม่มีโอกาสที่จะเกิดขึ้นกับแคชบัสเตอร์ที่โพสต์


0

หากคุณใช้ ASP.NET MVC ก็เพียงพอแล้วที่จะเพิ่มบรรทัดนี้ที่ด้านบนของแอ็คชันคอนโทรลเลอร์:

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

}

พฤติกรรมที่เป็นปัญหาอยู่ที่ฝั่งเบราว์เซอร์ คำตอบนี้เกี่ยวข้องกับการแคชบนฝั่งเซิร์ฟเวอร์
Mark Sowul

@MarkSowul Outputcache มี 3 ตัวเลือกไคลเอนต์เซิร์ฟเวอร์และอื่น ๆ IE ใช้ OutputCache เป็นค่าเริ่มต้นซึ่งส่วนใหญ่จะเป็นแคชฝั่งไคลเอ็นต์ สามารถดูรายละเอียดเพิ่มเติมได้ที่นี่dougwilsonsa.wordpress.com/2011/04/29/…
Emil

@MarkSowul คุณสามารถดูคำถามและคำตอบที่เกี่ยวข้องได้ที่นี่ คุณคิดว่านี่เป็นฝั่งเซิร์ฟเวอร์ด้วยหรือไม่? stackoverflow.com/questions/2653092/…
Emil

1
ใช่ขอโทษคุณพูดถูก - ฉันไม่ทราบว่าคำตอบของคุณอาจมีผลต่อทั้งแคชฝั่งเซิร์ฟเวอร์และแคชฝั่งไคลเอ็นต์
Mark Sowul

-1

IE อยู่ในสิทธิ์ในการทำแคชนี้ เพื่อให้แน่ใจว่ารายการไม่ได้ถูกแคชไว้ควรตั้งค่าส่วนหัวให้เหมาะสม

หากคุณใช้ ASP.NET MVC คุณสามารถเขียนActionFilter; ในการตรวจสอบOnResultExecuted filterContext.HttpContext.Request.IsAjaxRequest()ในกรณีนี้ให้ตั้งค่าส่วนหัวการหมดอายุของคำตอบ:filterContext.HttpContext.Response.Expires = -1;

ตามhttp://www.dashbay.com/2011/05/internet-explorer-caches-ajax/ :

บางคนชอบที่จะใช้ส่วนหัว Cache - Control: no - cache แทนการหมดอายุ นี่คือความแตกต่าง:
Cache-Control: no-cache - ไม่มีการแคชอย่างแน่นอน
หมดอายุ: -1 - เบราว์เซอร์ "โดยปกติ" จะติดต่อกับเว็บเซิร์ฟเวอร์เพื่ออัปเดตหน้านั้นผ่านคำขอ If-Modified-Since ตามเงื่อนไข อย่างไรก็ตามเพจยังคงอยู่ในดิสก์แคชและใช้ในสถานการณ์ที่เหมาะสมโดยไม่ต้องติดต่อกับเว็บเซิร์ฟเวอร์ระยะไกลเช่นเมื่อใช้ปุ่ม BACK และ FORWARD เพื่อเข้าถึงประวัติการนำทางหรือเมื่อเบราว์เซอร์อยู่ในโหมดออฟไลน์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.