60

我目前使用 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
        });
    }
4

10 回答 10

50

如我的其他帖子之一所述,您可以在 $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';
}]);
于 2014-05-15T15:03:19.143 回答
36

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

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

[OutputCache(NoStore = true, Duration = 0, VaryByParam = "None")]
public ActionResult Get()
{
    // return your response
}
于 2013-06-07T23:45:44.160 回答
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 }
    );
}
于 2014-11-07T10:17:14.667 回答
33

在 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();
});
于 2013-06-07T20:10:18.583 回答
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;
               }
           };
    });
于 2014-01-27T17:38:46.637 回答
4

我通过以下方式解决了它:

$http.get("/your_url?rnd="+new Date().getTime()).success(function(data, status, headers, config) {
    console.log('your get response is new!!!');
});
于 2014-07-25T10:51:11.000 回答
4

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;
}
于 2015-06-18T00:47:27.580 回答
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

根据规范

如果
接收到的字段值不是有效的 HTTP 日期,或者请求
方法既不是 GET 也不是 HEAD,接收者必须忽略 If-Modified-Since 头字段。

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

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

于 2015-03-02T10:07:15.940 回答
2

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

$templateCache.remove('/partials/details.html');
$state.go('details');
于 2015-05-29T18:38:50.797 回答
-3

一个明显的解决方案是使用唯一的 url。但是如何在初始化后更改路由器 url 禁用浏览器缓存不是一种选择,因为我们需要它来进行正常操作。当不再需要模板时,您可以从 $templateCache 中删除模板。(http://docs.angularjs.org/api/ng .$templateCache)。下载完成后,这些新的将立即添加到缓存中。

于 2013-09-19T07:18:07.427 回答