Ngăn chặn bộ nhớ cache của kết quả cuộc gọi AJAX


262

Có vẻ như nếu tôi tải nội dung động bằng cách sử dụng $.get(), kết quả được lưu trong bộ nhớ cache trong trình duyệt.

Thêm một số chuỗi ngẫu nhiên trong QueryString dường như để giải quyết vấn đề này (tôi sử dụng new Date().toString()), nhưng điều này cảm thấy giống như một vụ hack.

Có cách nào khác để đạt được điều này? Hoặc, nếu chuỗi duy nhất là cách duy nhất để đạt được điều này, bất kỳ đề xuất nào khác ngoài new Date()?


Bạn có thể sử dụng ký hiệu ngắn $.now()thay vì thực hiện (Ngày mới (). GetTime ()) mỗi lần.
Dayson

1
Tiêu đề câu hỏi của bạn là một chút sai lệch. Bạn có thể xem xét đổi tên nó?
0112

4
Bạn đã xem xét lựa chọn một câu trả lời khác là câu trả lời được chấp nhận?
M4N

Câu trả lời:


241

Tôi sử dụng new Date().getTime(), điều này sẽ tránh va chạm trừ khi bạn có nhiều yêu cầu xảy ra trong cùng một mili giây:

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

Chỉnh sửa: Câu trả lời này là vài năm tuổi. Nó vẫn hoạt động (do đó tôi chưa xóa nó), nhưng có nhiều cách tốt hơn / sạch hơn để đạt được điều này ngay bây giờ . Sở thích của tôi là cho này phương pháp, nhưng này câu trả lời cũng rất hữu ích nếu bạn muốn bộ nhớ đệm vô hiệu hóa cho mỗi yêu cầu trong suốt cuộc đời của một trang.


11
Tôi sẽ downvote chỉ vì nó sạch hơn khi để jQuery làm điều này như trong câu trả lời của Peter J. Giải pháp của bạn sẽ hoạt động, nhưng khó duy trì hơn trong thời gian dài.
Niklas Wulff

11
Phần nào của việc này đòi hỏi phải bảo trì? Khi so sánh với những gì jQuery làm?
Sunny R Gupta

5
Nó có thể là đáng chú ý là các new Date().getTime()code được sử dụng như thế này ... var nocache = new Date().getTime(); var path = 'http://hostname.domain.tld/api/somejsonapi/?cache=' + nocache;. Bản thân tôi đã mất vài phút để tìm ra cái đó. Tất nhiên ?cachecó thể là bất kỳ từ ngữ nào mà API không thực sự muốn.
doubleJ

1
+1 ngay cả câu trả lời của Peter J có cách tiếp cận tốt hơn câu trả lời này không sai cũng không phải là câu trả lời tồi. Tôi tin rằng DV được tạo bởi vì của bạn ở trên Peter (như được chấp nhận). và OP không xuất hiện trên SO từ đầu năm 2013
Michel Ayres

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

514

Việc sau đây sẽ ngăn tất cả các yêu cầu AJAX trong tương lai không được lưu vào bộ nhớ cache, bất kể bạn sử dụng phương thức jQuery nào ($ .get, $ .ajax, v.v.)

$.ajaxSetup({ cache: false });

7
Sau khi điều tra (Fiddler), có vẻ như jQuery thực hiện điều này trong nội bộ bằng cách đơn giản là nối thêm dấu thời gian (như đã thảo luận ở những nơi khác trong các câu trả lời này). Đối với tôi, phương pháp .ajaxSetup sạch hơn (theo ý kiến ​​của tôi.)
Peter J

8
Thật vậy, nó không cần phải ở trong tài liệu sẵn sàng gọi.
Peter J

19
Tại sao vô hiệu hóa bộ nhớ đệm ajax trên toàn cầu? Tôi nghĩ rằng nó nên được thực hiện trên cơ sở mỗi cuộc gọi, giống như những gì câu trả lời của Jonathan làm.
Sunny R Gupta

5
Bất cứ điều gì làm việc cho ứng dụng của bạn. Tôi tiếp tục sử dụng phương pháp này trong các ứng dụng thương mại bất cứ khi nào tôi thực sự cần dữ liệu mới cho tất cả các cuộc gọi AJAX. Đối với những người khác, dữ liệu lưu trữ là tốt.
Peter J

1
link Mô tả: Đặt giá trị mặc định cho các yêu cầu Ajax trong tương lai. Việc sử dụng nó không được khuyến khích.
itwebdeveloper

319

$ .Get () của JQuery sẽ lưu trữ các kết quả. Thay vì

$.get("myurl", myCallback)

bạn nên sử dụng $ .ajax, điều này sẽ cho phép bạn tắt bộ đệm ẩn:

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

62
+1 Đây là câu trả lời đúng. Giải pháp vô hiệu hóa bộ nhớ đệm trên toàn cầu của Peter J là một IMO thực hành tồi.
Salman von Abbas

7
Điều quan trọng cần lưu ý là nó chỉ "toàn cầu" cho trang / yêu cầu.
Peter J

3
+1: Bộ nhớ đệm phải dành riêng cho loại yêu cầu. Một số yêu cầu máy chủ có thể cần bộ nhớ đệm (trong đó dữ liệu máy chủ là tĩnh), do đó, chọn bộ đệm theo yêu cầu theo cơ sở yêu cầu tốt hơn là tắt tất cả .
Mã hóa

1
+1 cho câu trả lời đúng - ngăn chặn bộ nhớ đệm trên cơ sở mỗi cuộc gọi bằng phương pháp của jQuery, thay vì hack thủ công.
Đồi Brendan

2
Một câu trả lời tốt. Tôi phải nói rằng, đối với tôi, hầu hết thời gian vô hiệu hóa bộ nhớ cache trên toàn cầu đều mang lại lợi ích lớn. Tất cả phụ thuộc vào cách ứng dụng của bạn được thiết kế mặc dù. Không có viên đạn bạc, nhưng trong tình huống này, tôi muốn giới thiệu một hàm chấp nhận boolean cho bộ đệm, chức năng gọi lại và URL cho mô đun. Hướng dẫn sử dụng "hack" là tốt, nhưng nếu bạn đang sử dụng jQuery, hãy sử dụng các chức năng của chúng bất cứ khi nào có thể. Điều này sẽ không chỉ giúp phát triển dễ dàng hơn mà còn nâng cấp thư viện trong tương lai.
Anthony Mason

24

Tất cả các câu trả lời ở đây để lại dấu chân trên URL được yêu cầu sẽ hiển thị trong nhật ký truy cập của máy chủ.

Tôi cần một giải pháp dựa trên tiêu đề không có tác dụng phụ và tôi thấy có thể đạt được bằng cách thiết lập các tiêu đề được đề cập trong Cách kiểm soát bộ đệm ẩn trang web, trên tất cả các trình duyệt? .

Kết quả, hoạt động cho Chrome ít nhất, sẽ là:

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


Có thể là một câu hỏi ngu ngốc, nhưng nếu ajax của tôi trả lại hình ảnh, hình ảnh sẽ được lưu trữ? Để tránh các yêu cầu lớn của Amazon S3?
Marcelo Agimóvel

MarceloAgimóvel, đó có thể là một câu hỏi SO riêng biệt mà tôi tin.
Aidin

23

một cách khác là không cung cấp tiêu đề bộ đệm từ máy chủ trong mã tạo phản hồi cho lệnh gọi ajax:

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

17
Sai. Trong IE, các tiêu đề không có bộ đệm được bỏ qua cho các cuộc gọi XMLHttpRequest, như được thảo luận ở đây: stackoverflow.com/questions/244918/ Thẻ Phương thức DateTime (hoặc phương thức .ajaxSetup của tôi) là các giải pháp duy nhất thực sự hoạt động.
Peter J

Tôi vừa dán câu thần chú không có bộ nhớ cache thông thường của tôi, không nói rõ đó là IE cụ thể
mouseuz

2
Điều này sẽ tắt bộ nhớ đệm cho tất cả các trình duyệt: answer.setHeader ("Kiểm soát bộ đệm", "max-age = 0, không có bộ đệm, không lưu trữ, kiểm tra sau = 0, kiểm tra trước = 0");
Chris Broski

13

Cá nhân tôi cảm thấy rằng phương thức chuỗi truy vấn đáng tin cậy hơn so với việc cố gắng đặt các tiêu đề trên máy chủ - không có gì đảm bảo rằng proxy hoặc trình duyệt sẽ không lưu cache bằng mọi cách (một số trình duyệt còn tệ hơn các trình duyệt khác - không đặt tên).

Tôi thường sử dụng Math.random()nhưng tôi không thấy có gì sai khi sử dụng ngày (bạn không nên thực hiện các yêu cầu AJAX đủ nhanh để nhận được cùng một giá trị hai lần).


2
Kết hợp Ngày (). GetTime () cùng với Math.random () và bạn nên ở bên an toàn. Ngoài ra, Ext.Ajax cũng sử dụng getTime () khi vô hiệu hóa được chỉ định.
vividos

12

Theo tài liệu: http://api.jquery.com/jquery.ajax/

bạn có thể sử dụng cachetài sản với:

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

5

Tất nhiên các kỹ thuật "phá bộ nhớ cache" sẽ hoàn thành công việc, nhưng điều này sẽ không xảy ra ở nơi đầu tiên nếu máy chủ chỉ ra cho khách hàng rằng phản hồi không nên được lưu vào bộ đệm. Trong một số trường hợp có lợi cho phản hồi bộ đệm, một số lần thì không. Hãy để máy chủ quyết định tuổi thọ chính xác của dữ liệu. Bạn có thể muốn thay đổi nó sau. Dễ dàng thực hiện từ máy chủ hơn từ nhiều nơi khác nhau trong mã UI của bạn.

Tất nhiên điều này không có ích nếu bạn không có quyền kiểm soát máy chủ.


5

Còn việc sử dụng yêu cầu POST thay vì NHẬN ... thì sao? (Mà dù sao bạn cũng nên ...)


Tôi nghĩ đó là một giải pháp tốt hơn, nhưng thật đáng buồn là tôi (bằng cách nào đó) chỉ có thể thực hiện yêu cầu NHẬN. Vì vậy, bây giờ là ngày mới (). GetTime ().
Salamander2007

Vui lòng thêm một số giải thích cho câu trả lời của bạn để người khác có thể học hỏi từ nó - tại sao cần phải có một yêu cầu POST?
Nico Haase

5

Câu hỏi thực sự là tại sao bạn cần điều này để không được lưu trữ. Nếu không nên lưu vào bộ đệm vì nó thay đổi liên tục, máy chủ sẽ chỉ định để không lưu trữ tài nguyên. Nếu đôi khi nó chỉ thay đổi (vì một trong những tài nguyên mà nó phụ thuộc có thể thay đổi) và nếu mã máy khách có cách nhận biết về nó, nó có thể nối thêm một tham số giả vào url được tính từ một số băm hoặc ngày sửa đổi cuối cùng trong số các tài nguyên đó (đó là những gì chúng tôi làm trong tài nguyên tập lệnh Microsoft Ajax để chúng có thể được lưu trữ vĩnh viễn nhưng các phiên bản mới vẫn có thể được phục vụ khi chúng xuất hiện). Nếu máy khách không thể biết các thay đổi, cách chính xác là máy chủ sẽ xử lý các yêu cầu CHÍNH đúng cách và cho khách hàng biết có nên sử dụng phiên bản được lưu trong bộ nhớ cache hay không. Dường như với tôi như nối thêm một tham số ngẫu nhiên hoặc thông báo từ máy khách để không bao giờ lưu trữ bộ đệm là sai vì khả năng lưu trữ là một thuộc tính của tài nguyên máy chủ và do đó nên được quyết định phía máy chủ. Một câu hỏi khác để tự hỏi mình là tài nguyên này có thực sự được phục vụ thông qua GET hay nó nên đi qua POST? Đó là một câu hỏi về ngữ nghĩa, nhưng nó cũng có ý nghĩa bảo mật (có những cuộc tấn công chỉ hoạt động nếu máy chủ cho phép GET). POST sẽ không được lưu trữ.


6
Điều gì xảy ra nếu bạn đang đi qua các máy chủ proxy mà bạn không kiểm soát chính sách lưu trữ của họ? Điều gì xảy ra nếu ứng dụng của bạn rõ ràng cần phải thực hiện một yêu cầu mới mỗi lần? Câu trả lời cho mọi thứ không phải lúc nào cũng rõ ràng là cắt đen trắng, luôn có những vùng màu xám.
7wp

Đúng, nó không phải lúc nào cũng rõ ràng. Nhưng nhìn thấy câu trả lời này khiến tôi đặt câu hỏi về các giả định của mình và khiến tôi tìm ra nguyên nhân gốc rễ của vấn đề của mình. Đó có thể không phải là trường hợp cho tất cả mọi người, nhưng nó đã giúp tôi. Nếu bạn đang ở đây đọc nó, bạn cũng nên xem xét nó.
Jonathan Trần

Điều này đã giúp tôi, FeedbackCaching được đặt thành 60m phía máy chủ theo mặc định. Đã thay đổi nó thành No-Cache và nó đã dừng bộ đệm trên máy khách.
mattygee

4

Có lẽ bạn nên xem $ .ajax () thay vào đó (nếu bạn đang sử dụng jQuery, trông giống như vậy). Hãy xem: http://docs.jquery.com/Ajax/jQuery.ajax#options và tùy chọn "bộ đệm".

Một cách tiếp cận khác là xem xét cách bạn lưu trữ mọi thứ ở phía máy chủ.


1
Thật không may, sau một số điều tra, sử dụng $ .ajax () và đặt cache = false về cơ bản sẽ làm điều tương tự. jQuery sẽ thêm một số số ngẫu nhiên vào chuỗi truy vấn và nó không kiểm tra chuỗi truy vấn hiện có. Vì vậy, tôi đoán sử dụng $ .get () sẽ đủ.
Salamander2007

Ồ được. Chưa bao giờ thử nó, chỉ cần nhớ tôi đã thấy một cái gì đó về nó trong các tài liệu :)
finpingvin

Thậm chí không cần thiết phải sử dụng $ .ajax. Đơn giản chỉ cần sử dụng .ajaxSetup.
Peter J

3

Một bổ sung nhỏ cho các câu trả lời tuyệt vời được đưa ra: Nếu bạn đang chạy với một giải pháp sao lưu không phải là ajax cho người dùng không có javascript, bạn sẽ phải sửa các tiêu đề phía máy chủ đó. Điều này không phải là không thể, mặc dù tôi hiểu những người từ bỏ nó;)

Tôi chắc chắn có một câu hỏi khác về SO sẽ cung cấp cho bạn bộ tiêu đề đầy đủ phù hợp. Tôi không hoàn toàn trả lời con chuột trả lời bao gồm tất cả các cơ sở 100%.


3

Đối với những người sử dụng cachetùy chọn $.ajaxSetup()trên Safari trên thiết bị di động, có vẻ như bạn có thể phải sử dụng dấu thời gian cho POST, vì Safari cũng lưu trữ trên thiết bị di động. Theo tài liệu trên $.ajax()(mà bạn được hướng đến từ $.ajaxSetup()):

Đặt cache thành false sẽ chỉ hoạt động chính xác với các yêu cầu CHÍNH và NHẬN. Nó hoạt động bằng cách nối thêm "_ = {dấu thời gian}" vào tham số GET. Tham số này không cần thiết cho các loại yêu cầu khác, ngoại trừ trong IE8 khi POST được tạo cho một URL đã được GET yêu cầu.

Vì vậy, thiết lập tùy chọn đó sẽ không giúp bạn trong trường hợp tôi đã đề cập ở trên.


2

Về cơ bản chỉ cần thêm cache:false;vào ajax nơi bạn nghĩ nội dung sẽ thay đổi khi tiến trình tiếp tục. Và nơi mà nội dung sẽ không thay đổi ở đó bạn có thể bỏ qua điều này. Bằng cách này, bạn sẽ nhận được phản hồi mới mỗi lần



2

Giờ đây, thật dễ dàng để làm điều đó bằng cách bật / tắt tùy chọn bộ đệm trong yêu cầu ajax của bạn, giống như thế này

$(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
Sau 6 năm, bạn có cung cấp phản hồi tương tự như Jonathan không? ಠ_ಠ
redent84

mọi người có thể nói rằng 6 năm sau khi câu hỏi được đăng. Và câu trả lời của tôi cho câu hỏi đó là khác với bất kỳ ai khác, không đề cập đến nó là một câu trả lời đúng ngày nay. Trả lời những câu hỏi như vậy không dành cho "người hỏi", nó dành cho cộng đồng và người mới bắt đầu! Cảm ơn vì đã thêm làm rõ nào!
Omar El Don

Và sự khác biệt giữa của bạn và một stackoverflow.com/a/735084/469218 này là gì?
red84

có lẽ đó là sự rõ ràng, từ quan điểm của một người mới bắt đầu hỏi một câu hỏi như vậy !!
Omar El Don

1

Nếu bạn đang sử dụng IE 9, thì bạn cần sử dụng phần sau trước định nghĩa lớp trình điều khiển của mình:

[OutputCache (NoStore = true, Thời gian = 0, VaryByParam = "*")]

lớp công khai TestContoder: Trình điều khiển

Điều này sẽ ngăn trình duyệt lưu vào bộ nhớ cache.

Chi tiết về liên kết này: http://dougwilsonsa.wordpress.com/2011/04/29/diseac-ie9-ajax-response-caching-asp-net-mvc-3-jquery/

Trên thực tế điều này đã giải quyết vấn đề của tôi.


1

Như @Athasach đã nói, theo các tài liệu của jQuery, $.ajaxSetup({cache:false}) sẽ không hoạt động cho các yêu cầu GET và HEAD.

Bạn nên gửi lại Cache-Control: no-cache tiêu đề từ máy chủ của bạn. Nó cung cấp một sự tách biệt rõ ràng hơn của mối quan tâm.

Tất nhiên, điều này sẽ không hoạt động đối với các url dịch vụ mà bạn không thuộc về dự án của bạn. Trong trường hợp đó, bạn có thể xem xét ủy quyền dịch vụ bên thứ ba từ mã máy chủ thay vì gọi nó từ mã máy khách.


1

Nếu bạn đang sử dụng .net ASP MVC, hãy tắt bộ đệm ẩn trên hành động của bộ điều khiển bằng cách thêm thuộc tính sau vào chức năng điểm cuối:

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

Bạn có thể giải thích thêm? Làm thế nào mà mảng đó liên quan đến AJAX?
Nico Haase

Nó không phải là một mảng, nó là một thuộc tính trên Hành động của Trình điều khiển MVC.
Marius

0

thêm tiêu đề

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

Vui lòng thêm một số giải thích cho câu trả lời của bạn như vậy mà những người khác có thể học hỏi từ nó - nơi tiêu đề như vậy nên được bổ sung?
Nico Haase

-3

nối Math.random() vào url yêu cầu


2
Điều này sẽ cho kết quả không ổn định.
aj.toulan

Math.random sẽ chỉ hoạt động như một tham số, như url? _ = [Math.Random ()], nó không liên quan gì đến kết quả không ổn định.
xiaoyifang

4
Tôi hiểu những gì bạn đã làm. Tôi chỉ đơn thuần nhận xét rằng Math.Random () đôi khi sẽ cung cấp cho bạn cùng một số hai lần. Nếu bạn lấp đầy hệ thống của mình với sự không chắc chắn, chúng sẽ chỉ thêm vào nhau.
aj.toulan
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.