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

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

1、問題重現

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

public class HomeController : Controller{
public ActionResult Index(){
         return View();
    } 
public string GetCurrentTime(){
  return DateTime.Now.ToLongTimeString();
    }
}
<!DOCTYPE html>
<html>
<head>
<title>@ViewBag.Title</title>  
<script type="text/javascript" src="@Url.Coutent(「~/Scripts/jquery-1.7.1.min.js」)"></script>
<script type="text/javascript">
    $(function () {
        window.setInterval(function () {
        $.ajax({
            url:'@Url.Action("GetCurrentTime")',
            success: function (result) {
                $("ul").append("<li>" + result + "</li>");
            }
            });
        }, 5000);
    });
</script>
</head>
<body> 
<ul></ul>
</body>
</html>

採用不一樣的瀏覽器運行該程序會獲得不一樣的輸出結果,以下圖所示,Chrome瀏覽器中可以顯示出實時時間,可是在IE中顯示的時間都是相同的。java

2、經過爲URL地址添加後綴的方式解決問題

因爲IE針對Ajax請求的返回的結果是根據請求地址進行緩存的,因此若是不但願這個緩存機制生效,咱們能夠在每次請求時爲請求地址添加不一樣的後綴來解決這個問題。針對這個例子,咱們經過以下的代碼爲請求地址添加一個基於當前時間的查詢字符串,再次運行程序後IE中將會顯示實時的時間。jquery

<!DOCTYPE html>
<html>
     <head>        
         <script type="text/javascript">
             $(function () {
                 window.setInterval(function () {
                     $.ajax({
                         url:'@Url.Action("GetCurrentTime")?'+ new Date().toTimeString() ,
                         success: function (result) {
                             $("ul").append("<li>" + result + "</li>");
                         }
                     });
                 }, 5000);
             });
         </script>
     </head>
</html>

3、經過jQuery的Ajax設置解決問題

實際上jQuery具備針對這個的Ajax設置,咱們只須要按照以下的方式調用$.ajaxSetup方法禁止掉Ajaz的緩存機制。ajax

<!DOCTYPE html>
 <html>
     <head>        
         <script type="text/javascript">
             $(function () {
                 $.ajaxSetup({ cache: false }); 
                 window.setInterval(function () {
                     $.ajax({
                         url:'@Url.Action("GetCurrentTime")',
                         success: function (result) {
                             $("ul").append("<li>" + result + "</li>");
                         }
                     });
                 }, 5000);
             });
         </script>
     </head>
</html>

實際上jQuery的這個機制也是經過爲請求地址添加不一樣的查詢字符串後綴來實現的,這能夠經過Fiddler攔截的請求來證明。瀏覽器

4、經過定製響應解決問題

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

public class HomeController : Controller
 {
     public ActionResult Index()
     {
         return View();
     }
  
    [NoCache] 
     public string GetCurrentTime()
     {
         return DateTime.Now.ToLongTimeString();
     }
 }
 public class NoCacheAttribute : FilterAttribute, IActionFilter
 {
     public void OnActionExecuted(ActionExecutedContext filterContext)
     {
        filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
     }
  
     public void OnActionExecuting(ActionExecutingContext filterContext)
     {}
 }

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

HTTP/1.1 200 OK
 Server: ASP.NET Development Server/10.0.0.0
 Date: Thu, 03 Jan 2013 12:54:56 GMT
 X-AspNet-Version: 4.0.30319
 X-AspNetMvc-Version: 4.0
 Cache-Control: no-cache 
 Pragma: no-cache
 Expires: -1
 Content-Type: text/html; charset=utf-8
 Content-Length: 10
 Connection: Close
 8:54:56 PM
相關文章
相關標籤/搜索