2013-06-06 27 views
59

Tôi hiện đang sử dụng dịch vụ/$ tài nguyên để thực hiện cuộc gọi ajax (GET trong trường hợp này) và IE lưu trữ các cuộc gọi để dữ liệu mới không thể truy lục được từ máy chủ. Tôi đã sử dụng một kỹ thuật tôi tìm thấy bằng cách googling để tạo ra một số ngẫu nhiên và nối nó vào yêu cầu, để IE sẽ không đi vào cache cho dữ liệu.Cách nào tốt hơn để ngăn chặn trình duyệt IE trong AngularJS?

Có cách nào tốt hơn là thêm bộ nhớ cacheBất cứ yêu cầu nào không?

Code Factory

.factory('UserDeviceService', function ($resource) { 

     return $resource('/users/:dest', {}, { 
      query: {method: 'GET', params: {dest: "getDevicesByUserID"}, isArray: true } 
     }); 

Gọi từ bộ điều khiển

$scope.getUserDevices = function() { 
     UserDeviceService.query({cacheKill: new Date().getTime()},function (data) { 
      //logic 
     }); 
    } 
+2

Tôi đã thêm tiêu đề No-Cache trên phía máy chủ và nó làm việc cho bây giờ. –

+1

Ufuk, đó có vẻ là cách hiệu quả nhất để thực hiện chăm sóc vấn đề "toàn cầu" hoặc theo cách mở rộng hơn, mà không phải thực hiện mọi cuộc gọi ajax/REST duy nhất. Bạn nên trả lời câu hỏi, vì vậy tôi có thể đánh dấu câu hỏi đó là câu trả lời! Bạn xứng đáng với tín dụng. – binarygiant

+0

BTW, tôi đang sử dụng nút/Express cho máy chủ web và tôi đã hoàn thành những gì Ufuk đề xuất bằng cách thêm mã sau đây để diễn tả config: app.use (function noCache (req, res, next) { res.header ("Cache -Control "," no-cache, no-store, phải xác nhận lại "); res.header (" Pragma "," no-cache "); res.header (" Hết hạn ", 0); tiếp theo (); }) – binarygiant

Trả lời

33

Khi yêu cầu nhị phân, tôi đăng nhận xét của mình làm câu trả lời. Tôi đã giải quyết vấn đề này bằng cách thêm tiêu đề No-Cache vào phản hồi ở phía máy chủ. Lưu ý rằng bạn phải thực hiện điều này cho các yêu cầu GET, các yêu cầu khác dường như hoạt động tốt.

binarygiant đăng cách bạn có thể thực hiện việc này trên nút/tốc độ. Bạn có thể làm điều đó trong ASP.NET MVC như sau:

[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")] 
public ActionResult Get() 
{ 
    // return your response 
} 
+2

là có thực hiện DRY này không? – meffect

+1

@meffect Thêm nó như một bộ lọc toàn cầu có thể? –

+0

nó hoạt động cho tôi;) –

32

Kích hoạt nocache trong là ví dụ là cách tốt nhất để thực hiện điều này:

Trong nút/hiện các công trình này để ngăn chặn IE từ bộ nhớ đệm các yêu cầu đó:

app.use(function noCache(req, res, next) { 
    res.header("Cache-Control", "no-cache, no-store, must-revalidate"); 
    res.header("Pragma", "no-cache"); 
    res.header("Expires", 0); 
    next(); 
}); 
+0

Điều này cũng vô hiệu hóa bộ nhớ đệm trên các tệp tĩnh? tức là thư mục "công khai" của bạn? –

+0

@Tony, chỉ cần thêm phần mềm trung gian đó sau khi cung cấp các tệp tĩnh – Sentient

+0

cảm ơn công việc tuyệt vời – Chris

-3

Một giải pháp rõ ràng là sử dụng các url duy nhất. Nhưng làm thế nào có thể các url router được thay đổi khởi tạo bài Vô hiệu hóa bộ đệm trình duyệt không phải là một lựa chọn, vì chúng ta cần điều này cho các hoạt động bình thường. Bạn có thể xóa mẫu khỏi $ templateCache khi các mẫu đó không còn cần thêm nữa. (http://docs.angularjs.org/api/ng. $ TemplateCache). Các tính năng mới sẽ được thêm vào bộ nhớ cache ngay sau khi quá trình tải xuống hoàn tất.

12

bạn có thể thêm trình chặn chặn để tạo url yêu cầu duy nhất. Ngoài ra, bạn có thể loại bỏ console.log gọi

myModule.config(['$httpProvider', function($httpProvider) { 
$httpProvider.interceptors.push('noCacheInterceptor'); 
}]).factory('noCacheInterceptor', function() { 
      return { 
       request: function (config) { 
        console.log(config.method); 
        console.log(config.url); 
        if(config.method=='GET'){ 
         var separator = config.url.indexOf('?') === -1 ? '?' : '&'; 
         config.url = config.url+separator+'noCache=' + new Date().getTime(); 
        } 
        console.log(config.method); 
        console.log(config.url); 
        return config; 
       } 
      }; 
    }); 
+1

Một giải pháp đẹp hơn thay vì thao tác url sẽ là: kiểm tra xem yêu cầu có tham số 'config.params = config.params || [] 'và sau đó thêm tham số noCache mặc định của bạn' config.params ['noCache'] = new Date(). getTime(); ' – pasine

49

Như đã trình bày trong một trong những khác posts của tôi, bạn có thể vô hiệu hóa bộ nhớ đệm trên toàn cầu trong $ httpProvider:

myModule.config(['$httpProvider', function($httpProvider) { 
    //initialize get if not there 
    if (!$httpProvider.defaults.headers.get) { 
     $httpProvider.defaults.headers.get = {};  
    }  

    // Answer edited to include suggestions from comments 
    // because previous version of code introduced browser-related errors 

    //disable IE ajax request caching 
    $httpProvider.defaults.headers.get['If-Modified-Since'] = 'Mon, 26 Jul 1997 05:00:00 GMT'; 
    // extra 
    $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache'; 
    $httpProvider.defaults.headers.get['Pragma'] = 'no-cache'; 
}]); 
+1

JSHint có thể phàn nàn về' $ httpProvider.defaults.headers.get ['Pragma'] = 'no-cache'; 'để thay đổi dòng đó thành' $ httpProvider.defaults.headers.get.Pragma = 'no-cache'; ' – yvesmancera

+0

Tôi có thể không sử dụng những tính năng bổ sung đó không? – xlhuang

+1

Đối với những người bạn đang sử dụng Tài nguyên Góc, bạn phải thay thế $ httpProvider bằng $ resourceProvider – James

4

tôi làm cho nó giải quyết bằng cách:

$http.get("/your_url?rnd="+new Date().getTime()).success(function(data, status, headers, config) { 
    console.log('your get response is new!!!'); 
}); 
+0

Thiên Chúa chúc lành cho StackOverFlow! – SMir

33

Đối với những người sử dụng ASP.NET Web API 2, giải pháp tương đương sẽ là điều này (Web API không sử dụng cùng một bộ nhớ đệm logic như MVC):

public class NoCacheHeaderFilter : ActionFilterAttribute 
{ 
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) 
    { 
     if (actionExecutedContext.Response != null) // can be null when exception happens 
     { 
      actionExecutedContext.Response.Headers.CacheControl = 
       new CacheControlHeaderValue { NoCache = true, NoStore = true, MustRevalidate = true }; 
      actionExecutedContext.Response.Headers.Pragma.Add(new NameValueHeaderValue("no-cache")); 

      if (actionExecutedContext.Response.Content != null) // can be null (for example HTTP 400) 
      { 
       actionExecutedContext.Response.Content.Headers.Expires = DateTimeOffset.UtcNow; 
      } 
     } 
    } 
} 

sau đó đính kèm nó trong WebApiConfig.cs:

public static void Register(HttpConfiguration config) 
{ 
    .... 
    config.Filters.Add(new NoCacheHeaderFilter()); 

    config.Routes.MapHttpRoute(
     name: "DefaultApi", 
     routeTemplate: "api/{controller}/{id}", 
     defaults: new { id = RouteParameter.Optional } 
    ); 
} 
+4

Việc này đã giải quyết được vấn đề của chúng tôi. Chúng ta cũng phải thêm 'if (actionExecutedContext.Request.Method.Method ==" GET ")' vào sự kiện 'OnActionExecuted' để làm cho nó chỉ kích hoạt trên các yêu cầu GET – RichardC

+0

Tôi đã cập nhật mã cho một số trường hợp cạnh mà tôi đã tìm thấy. – UserControl

+3

Bạn sẽ phải so sánh với HttpMethod và không chỉ là chuỗi. Như thế này: 'actionExecutedContext.Request.Method == HttpMethod.Get' –

3

Trong khi phương pháp này:

myModule.config(['$httpProvider', function($httpProvider) { 
    //initialize get if not there 
    if (!$httpProvider.defaults.headers.get) { 
     $httpProvider.defaults.headers.get = {};  
    } 
    //disable IE ajax request caching 
    $httpProvider.defaults.headers.get['If-Modified-Since'] = '0'; 
}]); 

có phải là đúng, '0' không phải là một giá trị hợp lệ cho If-Modified-Since tiêu đề.Nó cần phải là một HTTP-ngày hợp lệ, ví dụ:

If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT 

Theo spec:

Một người nhận PHẢI bỏ qua If-Modified-Since header field nếu
nhận field- giá trị không phải là ngày HTTP hợp lệ hoặc nếu yêu cầu
, phương thức không phải là GET cũng như HEAD.

Vì vậy, hãy an toàn hơn xin lỗi và sử dụng ngày thực tế trong quá khứ.

Nếu bạn có bất kỳ kiểm soát nào đối với đầu ra của máy chủ, sẽ tốt hơn nếu không thêm tiêu đề bộ nhớ đệm vào thay vào đó.

2

Giải pháp của tôi đã thêm tiêu đề Cache-Control: no-cache trên máy chủ, cộng thêm $templateCache.remove() trước khi thay đổi trạng thái. Tôi đang sử dụng angular-ui/ui-router. Tôi đã gặp vấn đề với trình duyệt IE11 và Edge.

$templateCache.remove('/partials/details.html'); 
$state.go('details'); 
+0

Bạn có nghĩa là Cache-Control: no-cache? –

3

Koajs tương đương với câu trả lời của binarygiant:

app.use(route.get('*', noCache)); 

function* noCache(path, next){ 
    this.set('cache-control', 'no-cache, no-store, must-revalidate'); 
    this.set('pragma', 'no-cache'); 
    this.set('expires', 0); 
    yield next; 
} 
Các vấn đề liên quan