$ .getJSON trả về dữ liệu đã lưu trong bộ nhớ cache trong IE8


102

Tôi đang chơi với ASP.net MVC và JQuery vào lúc này. Tôi đã bắt gặp cách cư xử có vẻ không hợp lý.

Tôi đang gọi $.getJSONhàm của JQuery để điền một số div. Sự kiện được kích hoạt trên $(document).readysự kiện. Điều này hoạt động hoàn hảo.

AJAX.BeginFormmột giá trị nhỏ thêm một giá trị khác sẽ được sử dụng khi điền các div. Nó gọi hàm từ xa một cách chính xác và khi thành công sẽ gọi hàm javascript gốc để định vị lại các div.

Đây là phần kỳ lạ: Trong FireFox và Chrome - Mọi thứ đều hoạt động. NHƯNG Trong IE8 (Beta), lệnh gọi thứ hai này tới tập lệnh Div cư trú (gọi hàm $ .getJSON) nhận dữ liệu được lưu trong bộ nhớ cache và không yêu cầu máy chủ!

Hy vọng câu hỏi này có ý nghĩa: Trong một nut shell - Tại sao $.getJSONlấy dữ liệu được lưu vào bộ nhớ cache? Và tại sao nó chỉ ảnh hưởng đến IE8?


Thật kỳ lạ, tôi thấy lỗi này không chỉ trên IE mà cả Firefox nữa. Vô hiệu hóa bộ nhớ đệm ajax trong jquery đã giúp tôi.
Josef Sábl

Câu trả lời:


67

Xin thông báo cho bạn biết, Firefox và Chrome coi tất cả yêu cầu Ajax là không thể truy cập được. IE (tất cả các phiên bản) coi cuộc gọi Ajax giống như yêu cầu web khác. Đó là lý do tại sao bạn thấy hành vi này.
Cách buộc IE tải xuống dữ liệu theo từng yêu cầu:

  • Như bạn đã nói, hãy sử dụng tùy chọn 'cache' hoặc 'nocache' trong JQuery
  • Thêm một tham số ngẫu nhiên vào yêu cầu (xấu, nhưng hoạt động :))
  • Ở phía máy chủ, đặt khả năng truy cập (ví dụ: sử dụng một thuộc tính, xem bên dưới)

Mã:

public class NoCacheAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(ActionExecutedContext context)
    {
        context.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
    }
}

1
Giải pháp này hấp dẫn tôi. Tôi thực sự thích sự sang trọng của việc áp dụng một attibute trong MVC
Andrew Harry

1
Ngày nay có OOTB OutputCacheAttribute.
bzlm

1
@bzlm nhưng điều này là dễ dàng hơn để tìm kiếm
Simon_Weaver

kiểm tra formatinternet.wordpress.com/2010/01/14/… để biết giải pháp phía khách hàng
Ivo

1
Trên thực tế, nó là cách khác xung quanh, nhưng tôi đồng ý như một nhà phát triển trình duyệt IE đòi hỏi sự kiên nhẫn :)
Nico

107

Đây là cách nó làm việc cho tôi ...

$.ajaxSetup({ cache: false });
$.getJSON("/MyQueryUrl",function(data,item) {
     // do stuff with callback data
     $.ajaxSetup({ cache: true });
   });

Tôi đang vật lộn với vấn đề này và giải pháp của bạn đã đưa ra một cách nhanh chóng để giải quyết nó. :) Tôi có một câu hỏi, bạn có biết những tùy chọn nào có thể được sử dụng cho $ .ajaxSetup không? tài liệu hướng dẫn jQuery không cung cấp chi tiết không may ...
Achimnol

1
Các tùy chọn có sẵn giống hệt với $ .ajax Xem docs.jquery.com/Ajax/jQuery.ajax#options để biết thêm thông tin
Dan Esparza

12
Một cảnh báo nhỏ cho đoạn mã trên - nó chứa điều kiện chủng tộc. Bởi vì cuộc gọi và phản hồi của nó không đồng bộ, bạn nên gọi $.ajaxSetup({ cache: true });ngay sau getJSON()và không phải trong lệnh gọi lại.
sax

16

Cảm ơn Kent vì câu trả lời của bạn. Sử dụng $ .ajax ('{cache: no}'); hoạt động hoàn hảo. [biên tập]

Hoặc ít nhất tôi nghĩ rằng tôi đã làm. Có vẻ như jquery $ .getJSON không đọc bất kỳ thay đổi nào được thực hiện đối với đối tượng $ .ajax.

Giải pháp cuối cùng đã hoạt động là thêm một tham số mới theo cách thủ công

var noCache = Date();
$.getJSON("/somepage/someaction", { "noCache": noCache }, Callback);

độ phân giải ngày chỉ tính đến từng phút; điều đó có nghĩa là giải pháp này vẫn lưu trong bộ nhớ cache trong tối đa một phút. Điều này có thể chấp nhận được cho các mục đích của tôi.


9
var noCache = new Date (). getTime (); // sẽ cung cấp cho bạn với ms
scunliffe

cảm ơn Scunliffe! - Tôi khá mới để javascript, ASP MVC đã mở ra những chân trời mới cho tôi
Andrew Harry

Bạn cũng có thể thử một cái gì đó như Math.Random ().
Falkayn

@Falkayn - khó Math.Random()có thể được sử dụng, kết quả của nó sẽ không xác định và bạn có thể nhận được cùng một số hai lần liên tiếp (hoặc nhiều hơn). sử dụng new Date().getTime()sẽ đảm bảo rằng nó không bao giờ lặp lại. (trừ khi bạn có thể quay ngược thời gian;))
Dementic

11

Tôi đã giải quyết vấn đề tương tự này bằng cách đặt thuộc tính sau vào Hành động trong Bộ điều khiển:

[OutputCache(Duration = 0, VaryByParam = "None")]

Tuyệt vời! Thật tuyệt khi có các lựa chọn thay thế (tôi đã chọn cái này). Cảm ơn tất cả những người đóng góp!
Anders Juul

Hoạt động tốt với Asp.Net MVC 4.0
Mayank

4

Nếu bạn đang sử dụng ASP.net MVC, hãy xem xét thêm một phương thức mở rộng để dễ dàng triển khai không có bộ nhớ đệm như vậy:

    public static void NoCache(this HttpResponse Response)
    {
        Response.Cache.SetNoStore();
        Response.Cache.SetExpires(DateTime.MinValue);
        Response.Cache.SetCacheability(HttpCacheability.NoCache);
        Response.Cache.SetValidUntilExpires(false);

        Response.Expires = -1;
        Response.ExpiresAbsolute = DateTime.MinValue;
        Response.AddHeader("Cache-Control", "no-cache");
        Response.AddHeader("Pragma", "no-cache");
    }

Ý tưởng hay - vì vậy bạn gọi phương thức mở rộng này trên máy chủ trong khi gọi lại phải không?
Guy

2

Bạn có thể cần phải gửi một công cụ phá bộ nhớ cache.

Tôi khuyên bạn nên sử dụng $ .ajax ({cache: no}) để đề phòng (thêm hậu tố ngẫu nhiên vào yêu cầu nhận)

(Tôi có xu hướng sử dụng $ .ajax ở mọi nơi ngày nay, dễ điều chỉnh hơn)


Cảm ơn câu trả lời của bạn! ... Tôi vẫn chưa thử. Sẽ cung cấp trở lại thức ăn chăn nuôi trong thời gian ngắn
Andrew Harry

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.