UFO ET IT

AngularJS에서 IE 캐시를 방지하는 더 나은 방법?

ufoet 2020. 12. 2. 22:17
반응형

AngularJS에서 IE 캐시를 방지하는 더 나은 방법?


나는 현재 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
        });
    }

binarygiant가 요청했듯이 내 의견을 답변으로 게시하고 있습니다. 서버 측 응답에 No-Cache 헤더를 추가하여이 문제를 해결했습니다. GET 요청에 대해서만이 작업을 수행해야하며 다른 요청은 제대로 작동하는 것 같습니다.

binarygiant는 노드 / 익스프레스에서이를 수행하는 방법을 게시했습니다. 다음과 같이 ASP.NET MVC에서 수행 할 수 있습니다.

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

내 다른 게시물 중 하나에서 설명했듯이 $ 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';
}]);

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

is 인스턴스에서 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();
});

인터셉터를 추가하여 고유 한 요청 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;
               }
           };
    });

다음과 같이 해결됩니다.

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

Binarygiant의 대답에 해당하는 Koajs :

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;
}

이 접근 방식 :

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

사양 에 따르면 :

A recipient MUST ignore the If-Modified-Since header field if the
received field-value is not a valid HTTP-date, or if the request
method is neither GET nor HEAD.

So better be safe than sorry and use an actual date in the past.

If you have any control over the server output, it would be preferable to add no caching headers to that instead.


My solution was adding Cache-Control: no-cache header on the server, plus adding $templateCache.remove() before changing state. I'm using angular-ui/ui-router. I was having issue with IE11 and Edge browser.

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

An obvious solution is to use unique urls. But how can the router urls be changed post initialization Disabling browser caches is not an option, since we need this for normal operations. You could remove templates from the $templateCache when those are no longer needed. (http://docs.angularjs.org/api/ng.$templateCache). Those new ones are added to the cache as soon as downloading completes.

참고URL : https://stackoverflow.com/questions/16971831/better-way-to-prevent-ie-cache-in-angularjs

반응형