閱讀754 返回首頁    go 阿裏雲 go 技術社區[雲棲]


談談IE針對Ajax請求結果的緩存

在默認情況下,IE會針對請求地址緩存Ajax請求的結果。換句話說,在緩存過期之前,針對相同地址發起的多個Ajax請求,隻有第一次會真正發送到服務端。在某些情況下,這種默認的緩存機製並不是我們希望的(比如獲取實時數據),這篇文章就來簡單地討論這個問題,以及介紹幾種解決方案。

目錄
一、問題重現
二、通過為URL地址添加後綴的方式解決問題
三、通過JQuery的Ajax設置解決問題
四、通過定製響應解決問題

一、問題重現

我們通過一個ASP.NET MVC應用來重現IE針對Ajax請求結果的緩存。在一個空ASP.NET MVC應用中我們定義了如下一個默認的HomeController,其中包含一個返回當前時間的Action方法GetCurrentTime。

   1: public class HomeController : Controller
   2: {
   3:     public ActionResult Index()
   4:     {
   5:         return View();
   6:     }
   7:  
   8:     public string GetCurrentTime()
   9:     {
  10:         return DateTime.Now.ToLongTimeString();
  11:     }
  12: }

默認Action方法Index對應的View定義如下。我們每隔5秒鍾利用JQuery的方法以Ajax的方式調用GetCurrentTime操作,並將返回的結果顯示出來。

   1: <!DOCTYPE html>
   2: <html>
   3:     <head>
   4:         <title>@ViewBag.Title</title>  
   5:         <script type="text/javascript" src="@Url.Coutent(“~/Scripts/jquery-1.7.1.min.js”)"></script>
   6:         <script type="text/javascript">
   7:             $(function () {
   8:                 window.setInterval(function () {
   9:                     $.ajax({
  10:                         url:'@Url.Action("GetCurrentTime")',
  11:                         success: function (result) {
  12:                             $("ul").append("<li>" + result + "</li>");
  13:                         }
  14:                     });
  15:                 }, 5000);
  16:             });
  17:         </script>
  18:     </head>
  19:     <body> 
  20:         <ul></ul>
  21:     </body>
  22: </html>

采用不同的瀏覽器運行該程序會得到不同的輸出結果,如下圖所示,Chrome瀏覽器中能夠顯示出實時時間,但是在IE中顯示的時間都是相同的。

03210250-b997bc000e74414a9970234b6cded65
03210253-d8b60d982b354a0499106e03ededcad

二、通過為URL地址添加後綴的方式解決問題

由於IE針對Ajax請求的返回的結果是根據請求地址進行緩存的,所以如果不希望這個緩存機製生效,我們可以在每次請求時為請求地址添加不同的後綴來解決這個問題。針對這個例子,我們通過如下的代碼為請求地址添加一個基於當前時間的查詢字符串,再次運行程序後IE中將會顯示實時的時間。

   1: <!DOCTYPE html>
   2: <html>
   3:     <head>        
   4:         <script type="text/javascript">
   5:             $(function () {
   6:                 window.setInterval(function () {
   7:                     $.ajax({
   8:                         url:'@Url.Action("GetCurrentTime")?'+ new Date().toTimeString() ,
   9:                         success: function (result) {
  10:                             $("ul").append("<li>" + result + "</li>");
  11:                         }
  12:                     });
  13:                 }, 5000);
  14:             });
  15:         </script>
  16:     </head>
  17: </html>

 

三、通過jQuery的Ajax設置解決問題

實際上jQuery具有針對這個的Ajax設置,我們隻需要按照如下的方式調用$.ajaxSetup方法禁止掉Ajaz的緩存機製。

   1: <!DOCTYPE html>
   2: <html>
   3:     <head>        
   4:         <script type="text/javascript">
   5:             $(function () {
   6:                 $.ajaxSetup({ cache: false }); 
   7:                 window.setInterval(function () {
   8:                     $.ajax({
   9:                         url:'@Url.Action("GetCurrentTime")',
  10:                         success: function (result) {
  11:                             $("ul").append("<li>" + result + "</li>");
  12:                         }
  13:                     });
  14:                 }, 5000);
  15:             });
  16:         </script>
  17:     </head>
  18: </html>

實際上jQuery的這個機製也是通過為請求地址添加不同的查詢字符串後綴來實現的,這可以通過Fiddler攔截的請求來證實。

03210859-4c12a8b7a9c04781858dce592324c8f

四、通過定製響應解決問題

我們可以通過請求的響應來控製瀏覽器針對結果的緩存,為此我們定義了如下一個名為NoCacheAttribute的ActionFilter。在實現的OnActionExecuted方法中,我們調用當前HttpResponse的SetCacheability方法將緩存選項設置為NoCache。該NoCacheAttribute特性被應用到GetCurrentTime方法後,運行我們的程序在IE中依然可以得到實時的時間。

   1: public class HomeController : Controller
   2: {
   3:     public ActionResult Index()
   4:     {
   5:         return View();
   6:     }
   7:  
   8:     [NoCache] 
   9:     public string GetCurrentTime()
  10:     {
  11:         return DateTime.Now.ToLongTimeString();
  12:     }
  13: }
  14: public class NoCacheAttribute : FilterAttribute, IActionFilter
  15: {
  16:     public void OnActionExecuted(ActionExecutedContext filterContext)
  17:     {
  18:         filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
  19:     }
  20:  
  21:     public void OnActionExecuting(ActionExecutingContext filterContext)
  22:     {}
  23: }

實際NoCacheAttribute特性最終控製消息消息的Cache-Control報頭,並將其設置為“no-cache”,指示瀏覽器不要對結果進行緩存。如下所示的是針對GetCurrentTime請求的響應消息:

   1: HTTP/1.1 200 OK
   2: Server: ASP.NET Development Server/10.0.0.0
   3: Date: Thu, 03 Jan 2013 12:54:56 GMT
   4: X-AspNet-Version: 4.0.30319
   5: X-AspNetMvc-Version: 4.0
   6: Cache-Control: no-cache 
   7: Pragma: no-cache
   8: Expires: -1
   9: Content-Type: text/html; charset=utf-8
  10: Content-Length: 10
  11: Connection: Close
  12:  
  13: 8:54:56 PM

作者:蔣金楠
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
原文鏈接

最後更新:2017-10-25 16:04:12

  上一篇:go  如何解決jQuery Validation針對動態添加的表單無法工作的問題?
  下一篇:go  Ajax請求過程中顯示“進度”的簡單實現