2008-12-15 43 views
217

Có vẻ như nếu tôi tải nội dung động bằng cách sử dụng $.get(), kết quả sẽ được lưu trong bộ nhớ cache trong trình duyệt.Ngăn chặn bộ nhớ đệm trình duyệt của kết quả cuộc gọi jQuery AJAX

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 giống như một hack.

Có cách nào khác để đạt được điều này không? 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()?

+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ó không? – 0112

+4

Bạn đã cân nhắc chọn câu trả lời khác làm câu trả lời chưa? – M4N

Trả lời

204

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

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

Edit: Câu trả lời này là một vài tuổi. Nó vẫn hoạt động (do đó tôi đã không xóa nó), nhưng có những cách tốt hơn/sạch hơn để đạt được điều này ngay bây giờ. Tùy chọn của tôi là cho phương pháp this, nhưng câu trả lời là this cũng hữu ích nếu bạn muốn tắt bộ nhớ đệm cho mỗi yêu cầu trong suốt thời gian tồn tại của trang.

+11

Tôi sẽ downvote chỉ vì nó sạch hơn để cho 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ẽ làm việc, nhưng là khó khăn hơn để duy trì trong thời gian dài. –

+10

Phần nào trong số này yêu cầu bảo trì? Khi so sánh với những gì jQuery làm gì? –

+5

Cần lưu ý rằng mã 'new Date(). GetTime()' được sử dụng như thế này ... 'var nocache = new Date(). GetTime(); var path = 'http: //hostname.domain.tld/api/somejsonapi/? cache =' + nocache; '. Phải mất một vài phút tôi mới hiểu được điều đó. Tất nhiên '? Cache' có thể là bất kỳ từ ngữ nào mà API không thực sự muốn. – doubleJ

18

cách khác là cung cấp không có tiêu đề bộ nhớ cache từ phía máy chủ trong các mã mà tạo ra các phản ứng lời kêu gọi ajax:

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

Không đúng. Trong IE, các tiêu đề không có bộ nhớ cache được bỏ qua cho các cuộc gọi XMLHttpRequest, như được thảo luận tại đây: http://stackoverflow.com/questions/244918/internet-explorer-7-ajax-links-only-load-once DateTime (hoặc của tôi .ajaxSetup method) là giải pháp duy nhất thực sự hoạt động. –

+0

Tôi vừa dán chú thích bộ nhớ cache không có thông thường của mình, nó không nói rằng đó là IE cụ thể – miceuz

+1

Điều này sẽ tắt bộ nhớ đệm cho tất cả các trình duyệt: response.setHeader ("Cache-Control", "max-age = 0, no- cache, không lưu trữ, post-check = 0, pre-check = 0 "); –

13

Cá nhân tôi cảm thấy rằng phương pháp chuỗi truy vấn là đáng tin cậy hơn cố gắng để thiết lập 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 vào bộ đệm (một số trình duyệt kém hơn các trình duyệt khác - không đặt tên cho tên).

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

+2

Kết hợp Date(). GetTime() cùng với Math.random() và bạn nên ở bên an toàn. Trên một lưu ý phụ, Ext.Ajax cũng sử dụng getTime() khi disableCaching được chỉ định. – vividos

3

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

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 khi một số điều tra, sử dụng $ .ajax() và thiết lập cache = false về cơ bản sẽ làm điều tương tự. jQuery sẽ thêm một 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

+0

Ah okey. Không bao giờ thử nó, chỉ cần nhớ tôi đã nhìn thấy một cái gì đó về nó trong tài liệu :) – finpingvin

+0

Nó thậm chí không cần thiết để sử dụng $ .ajax. Đơn giản chỉ cần sử dụng .ajaxSetup. –

3

Một bổ sung nhỏ cho các câu trả lời xuất sắc nhất định: Nếu bạn đang chạy với một giải pháp sao lưu không phải ajax cho người dùng không có javascript, bạn sẽ phải nhận được các tiêu đề phía máy chủ đó. Điều này 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 phản đối chuột trả lời bao gồm tất cả các căn cứ 100%.

4

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 ngay từ đầu nếu máy chủ chỉ ra cho máy khách rằng phản hồi sẽ không được lưu trữ. Trong một số trường hợp, nó có lợi cho các phản hồi bộ nhớ cache, một số lần 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 này. Dễ dàng hơn nhiều để thực hiện từ máy chủ hơn từ nhiều nơi khác nhau trong mã giao diện người dùng của bạn.

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

4

Còn việc sử dụng yêu cầu POST thay vì GET ... thì sao? (Bạn nên làm gì ...)

+0

Tôi nghĩ đó là 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 GET. Vì vậy, nó là mới Date(). GetTime() cho bây giờ. – Salamander2007

267

JQuery's $ .get() sẽ lưu vào bộ nhớ cache kết quả. Thay vì

$.get("myurl", myCallback) 

bạn nên sử dụng $ .ajax, mà sẽ cho phép bạn để biến bộ nhớ đệm off:

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

+1 Đây là câu trả lời đúng. Giải pháp khắc phục bộ nhớ đệm toàn cầu của Peter J là một IMO thực hành tồi. –

+6

Quan trọng cần lưu ý rằng đó chỉ là "toàn cầu" cho trang/yêu cầu. –

+3

+1: Việc lưu vào bộ nhớ đệm phải cụ thể đối với loại yêu cầu. Một số yêu cầu máy chủ cũng có thể cần bộ nhớ đệm (nơi dữ liệu máy chủ là tĩnh), vì vậy việc chọn bộ nhớ đệm trên yêu cầu * theo yêu cầu * cơ sở tốt hơn là chỉ * tắt tất cả *. –

472

Sau đây sẽ ngăn chặn tất cả các yêu cầu AJAX tương lai khỏi bị lưu trữ, bất kể là jQuery phương pháp bạn sử dụng ($ .get, $ .ajax, v.v.)

$.ajaxSetup({ cache: false }); 
+4

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

+0

Đẹp và sạch - tuyệt vời! :-) –

+0

Tại sao điều này cần phải được bên trong cuộc gọi sẵn sàng tài liệu? Làm thế nào tôi có thể chắc chắn rằng không có tài liệu nào khác của tôi sẵn sàng xử lý (với các cuộc gọi ajax) sẽ bắn trước này? –

6

Câu hỏi thực sự là tại sao bạn không cần lưu trong bộ nhớ cache. Nếu nó không nên được lưu trữ bởi vì nó thay đổi tất cả các thời gian, máy chủ nên chỉ định để không cache tài nguyên. Nếu nó chỉ thay đổi đôi khi (vì một trong các tài nguyên mà nó phụ thuộc vào có thể thay đổi), và nếu mã khách hàng có cách biết về nó, nó có thể nối thông số giả vào url được tính từ một số băm hoặc ngày sửa đổi lần cuối của những 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 phiên bản mới vẫn có thể được phân phát khi chúng xuất hiện). Nếu khách hàng không thể biết được các thay đổi, cách chính xác nên cho máy chủ xử lý các yêu cầu HEAD đúng cách và cho khách hàng biết liệu 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ư thêm một tham số ngẫu nhiên hoặc nói từ máy khách để không bao giờ cache là sai vì cacheability là một tài sản 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 liệu 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 trong bộ nhớ cache.

+5

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

+0

Đú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 nghi ngờ các giả định của mình và dẫn tôi đến tìm nguyên nhân gốc rễ của vấn đề của tôi. Đó 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ày, bạn nên xem xét nó cũng có. –

13

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 và mọi lúc.

1

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

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

lớp công khai TestController: Bộ đ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ào liên kết này: http://dougwilsonsa.wordpress.com/2011/04/29/disabling-ie9-ajax-response-caching-asp-net-mvc-3-jquery/

Thực ra đây giải quyết vấn đề của tôi.

3

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

Đặt bộ nhớ cache thành sai sẽ chỉ hoạt động chính xác với yêu cầu HEAD và GET. Nó hoạt động bằng cách thêm "_ = {timestamp}" vào tham số GET. Thông 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 thành một URL đã được GET yêu cầu.

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

1

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

Bạn nên gửi lại tiêu đề Cache-Control: no-cache từ máy chủ của mình. Nó cung cấp một sự tách biệt các 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 dự án của bạn. Trong trường hợp đó, bạn có thể xem xét việc ủ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.

-3

thêm Math.random() đến địa chỉ yêu cầu

+1

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

+0

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

+3

Tôi hiểu những gì bạn đang làm. Tôi chỉ đơn thuần là bình luận 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 điền vào hệ thống của bạn với sự không chắc chắn, họ sẽ chỉ thêm vào đầu trang của nhau. –

2

Về cơ bản chỉ cần thêm cache:false; trong ajax nơi bạn nghĩ nội dung sẽ thay đổi như sự tiến bộ 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 u sẽ nhận được phản ứng mới mỗi khi

2

Internet Explorer’s Ajax Caching: What Are YOU Going To Do About It? đã đưa ra ba phương pháp:

  1. Thêm một bộ nhớ cache busting thẻ vào chuỗi truy vấn, như date = [timestamp]?. Trong jQuery và YUI, bạn có thể yêu cầu họ tự động thực hiện điều này.
  2. Sử dụng POST thay vì một GET
  3. Gửi một phản ứng tiêu đề HTTP mà cụ thể cấm các trình duyệt để cache nó
8

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

bạn có thể sử dụng cache bất động sản với:

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

Nếu bạn đang sử dụng .net ASP MVC, vô hiệu hóa bộ nhớ đệm trên hành động điều khiển bằng cách thêm thuộc tính sau vào hàm điểm kết thúc: [OutputCacheAttribute (VaryByParam = "*", Duration = 0, NoStore = true)]

2

Bây giờ, thật dễ dàng để làm điều đó bằng cách bật/tắt tùy chọn bộ nhớ cache trong yêu cầu ajax của bạn, chỉ cần 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); 
    } 
}); 
+1

Sau 6 năm bạn đang cung cấp cùng một phản ứng mà Jonathan? ಠ_ಠ – redent84

+0

mọi người có thể cho biết 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ỳ câu hỏi nào khác, chưa kể nó là một câu hỏi chính xác ngày nay. Trả lời những câu hỏi như vậy không phải 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 bạn đã thêm làm rõ! –

+0

Và sự khác nhau giữa bạn và http://stackoverflow.com/a/735084/469218 là gì? – redent84

12

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

Tôi cần giải pháp dựa trên tiêu đề không có tác dụng phụ và tôi nhận thấy nó có thể đạt được bằng cách thiết lập tiêu đề được đề cập trong How to control web page caching, across all browsers?.

Kết quả, làm việc cho Chrome ít nhất, sẽ là

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

+1

cảm ơn :) .............. – user889030

Các vấn đề liên quan