Bộ nhớ đệm kết quả AJAX bất ngờ trong IE8


135

Tôi đang gặp vấn đề nghiêm trọng với kết quả bộ nhớ đệm Internet Explorer từ yêu cầu JQuery Ajax.

Tôi có tiêu đề trên trang web của mình được cập nhật mỗi khi người dùng điều hướng đến một trang mới. Khi trang được tải, tôi làm điều này

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

Nó chỉ tiêm thông tin tiêu đề vào trang. Bạn có thể kiểm tra nó bằng cách truy cập www.wikipediamaze.com và sau đó đăng nhập và bắt đầu một câu đố mới.

Trong mọi trình duyệt tôi đã thử nghiệm (Google Chrome, Firefox, Safari, Internet Explorer), nó hoạt động rất tốt ngoại trừ trong IE. Eveything được tiêm tốt trong IE lần đầu tiên nhưng sau đó nó thậm chí không bao giờ thực hiện cuộc gọi đến /game/getpuzzleinfo. Nó giống như nó đã lưu trữ kết quả hoặc một cái gì đó.

Nếu tôi thay đổi cuộc gọi sang $.post("/game/getpuzzleinfo", ...IE, hãy chọn nó. Nhưng sau đó Firefox bỏ việc.

Ai đó có thể vui lòng làm sáng tỏ điều này về lý do tại sao IE lưu trữ $.getcác cuộc gọi ajax của tôi không?

CẬP NHẬT

Theo đề xuất bên dưới, tôi đã thay đổi yêu cầu ajax của mình thành điều này, điều này đã khắc phục vấn đề của tôi:

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

8
Cảm ơn đã hỏi điều này. Tôi không nói nên lời rằng trình duyệt này.
jjohn

1
Câu hỏi hay, và trang web thực sự mát mẻ. Ý tưởng tốt.
MikeMurko

Câu trả lời:


177

IE nổi tiếng với bộ nhớ đệm tích cực của các phản hồi Ajax. Khi bạn đang sử dụng jQuery, bạn có thể đặt tùy chọn toàn cầu:

$.ajaxSetup({
    cache: false
});

điều này sẽ khiến jQuery thêm một giá trị ngẫu nhiên vào chuỗi truy vấn yêu cầu, do đó ngăn IE lưu lại phản hồi.

Lưu ý rằng nếu bạn có các cuộc gọi Ajax khác đang diễn ra ở nơi bạn muốn lưu vào bộ đệm, thì điều này cũng sẽ vô hiệu hóa nó cho những cuộc gọi đó. Trong trường hợp đó, hãy chuyển sang sử dụng phương thức $ .ajax () và cho phép tùy chọn đó rõ ràng cho các yêu cầu cần thiết.

Xem http://docs.jquery.com/Ajax/jQuery.ajaxSetup để biết thêm thông tin.


1
Bạn cũng có thể thêm dấu thời gian vào cuối url. Không chắc chắn tại sao jQuery không đi theo cách tiếp cận này thay vào đó.
Eric Johnson

14
@Eric: đó là những gì jQuery thực hiện trong nội bộ - tùy chọn "cache: false" chỉ bảo nó làm điều đó.
NickFitz

Tại sao jquery không có cái này theo mặc định?
bay tốc độ

Tôi chỉ nhận thấy rằng các tùy chọn bộ đệm không hoạt động khi bạn cố gắng yêu cầu trang chủ trong IE 8, với một cuộc gọi đến /. Thay đổi nó thành /index.phphoặc bất cứ điều gì url đầy đủ có thể được. Hoặc tự thêm một số thông số giả như/?f=f
Hugo Delsing

8

Như marr75 đã đề cập, GET's được lưu trữ.

Có một vài cách để chống lại điều này. Ngoài việc sửa đổi tiêu đề phản hồi, bạn cũng có thể nối thêm biến chuỗi truy vấn được tạo ngẫu nhiên vào cuối URL được nhắm mục tiêu. Theo cách này, IE sẽ nghĩ rằng đó là một URL khác nhau mỗi lần được yêu cầu.

Có nhiều cách để làm điều này (chẳng hạn như sử dụng Math.random(), một biến thể vào ngày, v.v.).

Đây là một cách bạn có thể làm điều đó:

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

3

Gets luôn được lưu trữ. Một chiến lược có thể hoạt động là chỉnh sửa tiêu đề phản hồi và yêu cầu khách hàng không lưu trữ thông tin hoặc sớm hết hạn bộ đệm.


Có vẻ là một ý tưởng tốt. Làm thế nào tôi sẽ đi về làm điều đó?
Mi-chê

1
Đó là một câu hỏi được tải, phụ thuộc vào mã phía máy chủ của bạn. Xem mục wikipedia "Danh sách các tiêu đề HTTP" để biết hướng dẫn. Ví dụ: Kiểm soát bộ đệm: không có bộ nhớ cache Hết hạn: Thu, ngày 01 tháng 12 năm 1994 16:00:00 GMT Về cơ bản, bạn cần phải nối các tiêu đề phản hồi này vào phản hồi http của mình. Nó khá đơn giản trong ASP.NET, Ruby và PHP. Chỉ cần tra cứu ngôn ngữ phía máy chủ mà bạn đang sử dụng + sửa đổi các tiêu đề phản hồi.
marr75

3
Ngoài ra, và đây hoàn toàn không phải là một lời chỉ trích của Jquery (tôi thích thư viện đó), phương pháp thêm một tham số chuỗi truy vấn ngẫu nhiên là an toàn nhưng bất lịch sự với khách hàng (nó có thể khiến họ giữ các mục trong bộ nhớ cache sẽ không bao giờ được sử dụng lần nữa).
marr75

2

Nếu bạn đang gọi trang ashx, bạn cũng có thể tắt bộ đệm ẩn trên máy chủ với mã sau:

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

1

đây là những gì tôi làm cho các cuộc gọi ajax:

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

nó hoạt động khá tốt đối với tôi


1

NickFitz đưa ra một câu trả lời hay, nhưng bạn cũng cần tắt bộ nhớ đệm trong IE9. Để nhắm mục tiêu chỉ IE8 và IE9, bạn có thể làm điều này;

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

0

Các câu trả lời ở đây rất hữu ích cho những người sử dụng jQuery hoặc vì một số lý do trực tiếp sử dụng đối tượng xmlHttpRequest ...

Nếu bạn đang sử dụng proxy dịch vụ Microsoft được tạo tự động, việc giải quyết không đơn giản.

Mẹo nhỏ là sử dụng phương thức Sys.Net.WebRequestManager.add_invokingRequest trong trình xử lý sự kiện thay đổi url yêu cầu:

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

Tôi đã viết về điều này: http://yoavniran.wordpress.com/2010/04/27/ie-caching-ajax-results-how-to-fix/


0

Chỉ cần viết một blog về vấn đề chính xác này chỉ bằng cách sử dụng ExtJS ( http://thecodablesode.blogspot.com/2010/10/cache-busting-ajax-requests-in-ie.html )

Vấn đề là khi tôi đang sử dụng một định dạng viết lại url cụ thể, tôi không thể sử dụng params chuỗi truy vấn thông thường (? Param = value), vì vậy tôi đã viết tham số phá vỡ bộ đệm như một biến được đăng thay thế ..... Tôi đã nghĩ rằng sử dụng các biến POST sẽ an toàn hơn một chút so với GET, đơn giản vì rất nhiều khung MVC sử dụng mẫu

giao thức: // máy chủ / bộ điều khiển / hành động / param1 / param2

và do đó, ánh xạ của tên biến thành giá trị bị mất và các tham số được xếp chồng đơn giản ... vì vậy khi sử dụng tham số buster bộ đệm GET

tức là giao thức: // host / control / action / param1 / param2 / no_cache122300201

no_cache122300201 có thể bị nhầm với tham số $ param3 có thể có giá trị mặc định

I E

hành động chức năng công cộng ($ param1, $ param2, $ param3 = "giá trị mặc định") {//..//}

không có cơ hội điều đó xảy ra với bộ đệm cache POSTED


0

Nếu bạn đang sử dụng ASP.NET MVC, việc thêm dòng này lên trên hành động của bộ điều khiển là đủ.

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

}

Hành vi trong câu hỏi là về phía trình duyệt; câu trả lời này liên quan đến bộ nhớ đệm ở phía máy chủ.
Mark Sowul

@MarkSowul Outputcache có 3 tùy chọn Client, Server và bất kỳ. IE sử dụng OutputCache làm mặc định bất kỳ phần nào đi vào bộ đệm ẩn phía máy khách. Bạn có thể xem thêm chi tiết tại đây dougwilsonsa.wordpress.com/2011/04/29/ trên
batmaci

@MarkSowul bạn cũng có thể xem câu hỏi và câu trả lời liên quan ở đây. Bạn có nghĩ rằng điều này cũng ở phía máy chủ? stackoverflow.com/questions/2653092/
hy

1
Vâng, xin lỗi, bạn nói đúng - Tôi không nhận ra rằng câu trả lời của bạn có thể ảnh hưởng đến cả bộ đệm phía máy chủ và bộ đệm phía máy khách.
Mark Sowul

-1

IE có quyền thực hiện bộ nhớ đệm này; để đảm bảo mục không được lưu trong bộ nhớ cache, các tiêu đề phải được đặt tương ứng.

Nếu bạn đang sử dụng ASP.NET MVC, bạn có thể viết một ActionFilter ; trong OnResultExecuted, kiểm tra filterContext.HttpContext.Request.IsAjaxRequest(). Nếu vậy, hãy đặt tiêu đề hết hạn của phản hồi:filterContext.HttpContext.Response.Expires = -1;

Theo http://www.dashbay.com/2011/05/iNET-explorer-caches-ajax/ :

Một số người thích sử dụng tiêu đề Cache - Control: no - cache thay vì hết hạn. Đây là sự khác biệt:
Kiểm soát bộ đệm: không có bộ đệm - hoàn toàn KHÔNG có bộ nhớ đệm
Hết hạn: -1 - trình duyệt Thông thường, liên lạc với máy chủ Web để cập nhật trang đó thông qua yêu cầu If-Modified-Because có điều kiện. Tuy nhiên, trang vẫn nằm trong bộ đệm đĩa và được sử dụng trong các tình huống thích hợp mà không liên hệ với máy chủ Web từ xa, chẳng hạn như khi các nút BACK và FORWARD được sử dụng để truy cập lịch sử điều hướng hoặc khi trình duyệt ở chế độ ngoại tuyến.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.