更好的方法来防止AngularJS中的IE缓存?

时间:2013-06-06 20:44:02

标签: caching angularjs

我目前使用service / $ resource来进行ajax调用(在这种情况下为GET),并且IE缓存调用以便无法从服务器检索新数据。我使用了一种通过谷歌搜索找到的技术来创建一个随机数并将其附加到请求中,这样IE就不会去缓存数据了。

有没有比将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
        });
    }

10 个答案:

答案 0 :(得分:50)

如我的其他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 :(得分:36)

as binarygiant要求我发布我的评论作为答案。我通过向服务器端的响应添加No-Cache标头解决了这个问题。请注意,您必须仅对GET请求执行此操作,其他请求似乎可以正常工作。

binarygiant发布了如何在node / express上执行此操作。您可以在ASP.NET MVC中执行此操作:

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

答案 2 :(得分: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 }
    );
}

答案 3 :(得分:32)

在is实例中启用noCache是​​实现此目的的最佳方法:

在node / express中,这可以防止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();
});

答案 4 :(得分:12)

您可以添加一个拦截器来生成唯一的请求网址。您也可以删除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;
               }
           };
    });

答案 5 :(得分:4)

我通过以下方式解决了问题:

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

答案 6 :(得分: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。

最好是安全而不是抱歉并使用过去的实际日期。

如果您对服务器输出有任何控制权,那么最好不要为其添加缓存标头。

答案 7 :(得分: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;
}

答案 8 :(得分:2)

我的解决方案是在服务器上添加Cache-Control: no-cache标头,并在更改状态之前添加$templateCache.remove()。我正在使用angular-ui / ui-router。我遇到了IE11和Edge浏览器的问题。

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

答案 9 :(得分:-3)

一个明显的解决方案是使用唯一的网址。但是如何在初始化后更改路由器URL 禁用浏览器缓存不是一种选择,因为我们需要将其用于正常操作。 如果没有,您可以从$ templateCache中删除模板 需要更久。 (http://docs.angularjs.org/api/ng。$ templateCache)。 一旦下载完成,这些新的就会被添加到缓存中。