2013-06-06 2 views
59

В настоящее время я использую service/$ resource для создания ajax-вызовов (GET в этом случае), а IE кэширует вызовы, чтобы свежие данные не могли быть получены с сервера. Я использовал технику, которую я нашел в Google для создания случайного числа и добавил его в запрос, чтобы IE не переходил к кешу для данных.Лучший способ предотвратить кеш IE в AngularJS?

Есть ли лучший способ, чем добавление cacheKill к каждому запросу?

завода код

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

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

вызова от контроллера

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

Я добавил заголовки No-Cache на стороне сервера, и она работала на данный момент. –

+1

Ufuk, это, по-видимому, самый эффективный способ заботиться о проблеме «глобально» или более масштабируемым образом, без необходимости сделать каждый уникальный вызов ajax/REST уникальным. Вы должны ответить на вопрос, поэтому я могу отметить это как ответ! Вы заслуживаете кредита. – binarygiant

+0

BTW, я использую node/express для веб-сервера, и я выполнил то, что рекомендовал Ufuk, добавив следующий код для выражения конфигурации: app.use (функция noCache (req, res, next) { res.header ("Cache -Control "," no-cache, no-store, must-revalidate "); res.header (" Pragma "," no-cache "); res.header (" Истекает ", 0); next () }) – binarygiant

ответ

33

Как запрошен binarygiant Я отправляю свой комментарий в качестве ответа. Я решил эту проблему, добавив заголовки No-Cache к ответу на стороне сервера. Обратите внимание, что вы должны делать это только для запросов GET, другие запросы работают нормально.

binarygiant опубликовано, как вы можете это сделать на узле/экспресс. Вы можете сделать это в ASP.NET MVC следующим образом:

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

есть ли сухая реализация этого? – meffect

+1

@meffect Добавление его как глобального фильтра может быть? –

+0

это работает для меня;) –

32

Благоприятного NoCache в экземпляре является лучшим способом для достижения этой цели:

В узле/выразить это работает, чтобы предотвратить IE от кеширования этих запросов:

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

Это также отключает кеширование статических файлов? т.е. ваша «общедоступная» папка? –

+0

@Tony, просто добавьте это промежуточное программное обеспечение после обслуживания статических файлов – Sentient

+0

спасибо, отлично работает – Chris

-3

Очевидным решением является использование уникальных URL-адресов. Но как изменить URL-адреса маршрутизатора после инициализации Отключение кэширования браузеров не является вариантом, так как это необходимо для нормальной работы. Вы можете удалить шаблоны из $ templateCache, если они не нужны . (http://docs.angularjs.org/api/ng. $ TemplateCache). Эти новые добавляются в кеш, как только загрузка завершается.

12

вы можете добавить перехватчик для создания уникального URL-адреса запроса. Кроме того, вы можете удалить console.log вызовы

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

Лучшим решением вместо управления URL будет: проверить, есть ли у запроса параметры 'config.params = config.params || [] ', а затем добавить свой параметр noCache по умолчанию' config.params ['noCache'] = new Date(). getTime(); ' – pasine

49

Как описано в одном из моих других posts, можно отключить кэширование глобально в $ 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 может жаловаться на' $ httpProvider.defaults.headers.get ['Pragma'] = 'no-cache'; 'поэтому безопасно изменить эту строку на' $ httpProvider.defaults.headers.get.Pragma = 'no-cache'; ' – yvesmancera

+0

Могу ли я не использовать эти дополнительные функции? – xlhuang

+1

Для тех из вас, кто использует Угловой ресурс, вы должны подставить $ httpProvider $ resourceProvider – James

4

Я получаю это разрешаться:

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

Бог благословляет StackOverFlow! – SMir

33

Для тех, кто использует ASP.NET Web API 2, это эквивалентное решение (Web API не использует такую ​​же логику кэширования, как 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; 
      } 
     } 
    } 
} 

затем прикрепить его в 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

Это решило нашу проблему. Мы также должны были добавить 'if (actionExecutedContext.Request.Method.Method ==" GET ")' в событие 'OnActionExecuted', чтобы сделать его только огнем в запросах GET. – RichardC

+0

Я обновил код для некоторых случаев краев, которые я нашел. – UserControl

+3

Вам нужно будет сравнить с HttpMethod, а не только с строкой. Например: 'actionExecutedContext.Request.Method == HttpMethod.Get' –

3

Хотя такой подход:

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'; 
}]); 

правильно, '0' не является допустимым значением для If-Modified-Since заголовок.Он должен быть действительным HTTP-дата, например:

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

Согласно spec:

Получатель должен игнорировать If-Modified-Since поле заголовка, если
получил поле- значение не является допустимой HTTP-датой, или если метод
не является ни GET, ни HEAD.

Так что лучше быть в безопасности, чем жалеть, и использовать фактическую дату в прошлом.

Если у вас есть какой-либо контроль над выходом сервера, было бы предпочтительнее добавлять вместо этого кеширующие заголовки.

2

Мое решение добавляло заголовок Cache-Control: no-cache на сервер, а также добавляя $templateCache.remove() перед изменением состояния. Я использую угловой ui/ui-router. У меня возникла проблема с браузерами IE11 и Edge.

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

Вы имеете в виду Cache-Control: no-cache? –

3

Koajs эквивалент ответа 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; 
}