Угловая проблема кэширования IE для $ http


251

Все ajax-вызовы, отправляемые из IE, кэшируются Angular, и я получаю a 304 responseдля всех последующих вызовов. Хотя запрос такой же, ответ не будет таким же в моем случае. Я хочу отключить этот кеш. Я попытался добавить в cache attribute$ http.get, но все равно это не помогло. Как можно решить эту проблему?

Ответы:


439

Вместо того, чтобы отключать кэширование для каждого отдельного GET-запроса, я отключаю его глобально в $ 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';
}]);

78
В If-Modified-Sinceзаголовке IIS + марка iisnode бросок 400 Bad Request для каждого HTML файла , загруженного через ngIncludeи ngView. Следующие два заголовка исправили эту проблему для меня (я вытащил их из Chrome, у которого не было проблемы с кэшированием): $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache'; $httpProvider.defaults.headers.get['Pragma'] = 'no-cache';
Langdon

4
По моему мнению, этот ответ должен быть помечен как ответ, в то время как решение, предоставленное Мартином, работает, это скорее взлом, чем реальное исправление.
Робба

4
Это сработало для моих локальных запросов GET, но заставило один запрос CORS, который я делал, начать использовать метод OPTIONS вместо метода GET. Сторонний сервер не поддерживает метод OPTIONS, поэтому мой обходной путь - использовать jQuery.get () для выполнения этого запроса и использовать $ scope.apply () в обработчиках ответов.
Бен

13
Использование If-Modified-Since = "0"заголовка ломает Tomcat (проблема с разбором даты заголовка, так как 0недопустимое значение RFC ). Исправлено использование значения Mon, 26 Jul 1997 05:00:00 GMTвместо.
Лописан

6
Я не использовал заголовок «If-Modified-Since», и он работал без этого. Просто два других необходимы.
Майкл Махони

69

Вы можете добавить уникальную строку запроса (я думаю, именно это jQuery делает с опцией cache: false) к запросу.

$http({
    url: '...',
    params: { 'foobar': new Date().getTime() }
})

Возможно, лучшим решением будет то, что если у вас есть доступ к серверу, вы можете убедиться, что для предотвращения кэширования установлены необходимые заголовки. Если вы используете ASP.NET MVC этот ответ, может помочь.


2
$http.get(url+ "?"+new Date().toString())это просто другое представление, без использования параметра, но добавление его в строку запроса.
Давут Гюрбюз

28

Вы можете добавить перехватчик.

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

Вы должны удалить строки console.log после проверки.


И вы должны использовать $logв случае, если вы забудете вынуть их.
Карл Дж

2
У меня серьезные проблемы с кэшированием в IE, что приводит к пустой странице, потому что важные части не выполняются. Использование этого перехватчика решило эту проблему! +1
Раулински

Я думаю, что это лучший подход, поскольку он позволяет избежать проблем с поведением CORS и IE при запуске предварительного запроса, если вы добавляете дополнительные заголовки. Похоже, это самый безопасный способ
избежать

@dilip pattnaik: - Почему эта проблема возникает с угловой и т. е.?
MiHawk

14

Я просто добавил три мета-тега в index.html для углового проекта, и проблема с кешем была решена в IE.

<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache">
<meta http-equiv="Expires" content="Sat, 01 Dec 2001 00:00:00 GMT">

2
У нас уже были эти метатеги, index.htmlкогда мы заметили, что IE11 кэширует AJAX-запросы: / Но настройка, $httpProviderкак показано в других ответах, работала нормально.
Walen

14

Дублирую мой ответ в другой ветке .

Для Angular 2 и новее самый простой способ добавить no-cacheзаголовки, переопределив RequestOptions:

import { Injectable } from '@angular/core';
import { BaseRequestOptions, Headers } from '@angular/http';

@Injectable()
export class CustomRequestOptions extends BaseRequestOptions {
    headers = new Headers({
        'Cache-Control': 'no-cache',
        'Pragma': 'no-cache',
        'Expires': 'Sat, 01 Jan 2000 00:00:00 GMT'
    });
}

И сослаться на это в вашем модуле:

@NgModule({
    ...
    providers: [
        ...
        { provide: RequestOptions, useClass: CustomRequestOptions }
    ]
})

Разве это не заголовки для ответа сервера, а не для запроса браузера? (Я мог бы представить, что можно установить If-Modified-Sinceс какой-то датой в далеком прошлом, используя описанный выше метод.)
Арджан

@Vitaliy: - Почему эта проблема возникает с угловым и т. Д.?
MiHawk

Ваш подход удалит все пользовательские заголовки, которые уже есть. Следовательно, сделайте следующее вместо создания нового объекта заголовка. headers: req.headers .set('Cache-Control', 'no-cache') .set('Pragma', 'no-cache') .set('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT')
Чамика Гунетилака

9

Гарантированный, что я работал, был чем-то вроде этого:

myModule.config(['$httpProvider', function($httpProvider) {
    if (!$httpProvider.defaults.headers.common) {
        $httpProvider.defaults.headers.common = {};
    }
    $httpProvider.defaults.headers.common["Cache-Control"] = "no-cache";
    $httpProvider.defaults.headers.common.Pragma = "no-cache";
    $httpProvider.defaults.headers.common["If-Modified-Since"] = "Mon, 26 Jul 1997 05:00:00 GMT";
}]);

Я должен был объединить 2 из вышеуказанных решений для того , чтобы гарантировать правильное использование всех методам, но вы можете заменить commonс getили другим методом , то есть put, post, deleteчтобы сделать эту работу для различных случаев.


Можете ли вы сказать мне, где в коде вы добавили это в файл angular.js? какая строка #?
JonathanScialpi

@JonathanScialpi Я обновил это, чтобы показать, где я мог бы поместить это. Где это находится внутри анонимной функции, не должно иметь значения.
марксизм

@marksyzm Можете ли вы сказать мне, что означает эта строкаif (!$httpProvider.defaults.headers.get) { $httpProvider.defaults.headers.common = {}; }
Monojit Sarkar

@MonojitSarkar Ах, это должно было быть headers.common в операторе if, спасибо за этот указатель
marksyzm

1
["If-Modified-Since"] = "0"является незаконным и с генерацией плохого запроса на некоторых бэкэндах. это должно быть свидание.
Дженсон Баттон: мероприятие

8

Мне помогла только эта строка (Angular 1.4.8):

$httpProvider.defaults.headers.common['Pragma'] = 'no-cache';

UPD: проблема в том, что IE11 делает агрессивное кэширование. Когда я заглянул в Fiddler, я заметил, что в режиме F12 отправляются запросы "Pragma = no-cache", и конечная точка запрашивается при каждом посещении страницы. Но в обычном режиме конечная точка запрашивалась только один раз при первом посещении страницы.


1
Только к вашему сведению, этот ответ вызвал проблему CORS при запросе файлов из хранилища BLOB-объектов Azure, которую было трудно отследить, но в конце концов выяснили, что это было причиной. Удаление заголовка прагмы устранило мою проблему с CORS (но вновь установила проблему с кэшированием в IE).
keithl8041

7

Чтобы избежать кеширования, можно указать разные URL-адреса для одного и того же ресурса или данных. Чтобы создать другой URL, вы можете добавить случайную строку запроса в конец URL. Этот метод работает для запросов AJAX JQuery, Angular или других типов.

myURL = myURL +"?random="+new Date().getTime();

6

Я получаю это решенное добавление даты и времени как случайного числа:

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

: - Почему эта проблема возникает с угловой и т. Е.?
MiHawk

4

Решение, приведенное выше, будет работать (сделайте URL уникальным, добавив в строку запроса новый параметр), но я предпочитаю решение, предлагаемое [здесь]: Лучший способ предотвратить кеширование IE в AngularJS?, которые обрабатывают это на уровне сервера, поскольку это не относится к IE. Я имею в виду, что если этот ресурс не должен быть кэширован, делайте это на сервере (это никак не связано с используемым браузером; это сложно для ресурса).

Например, в java с JAX-RS сделайте это программно для JAX-RS v1 или декларативно для JAX-RS v2.

Я уверен, что кто-нибудь поймет, как это сделать


1
Хотя это может быть разработано, это правильный способ сделать это. Клиентская сторона не должна выбирать, что кэшировать или нет, но именно сервер должен сообщать клиенту, что нужно кэшировать или нет.
Архимед Траяно

Я полностью согласен, это должен быть правильный путь
smnbbrv

1

Это немного по-старому, но: решения вроде устарели. Пусть сервер обрабатывает кеш или не кеш (в ответе). Единственный способ гарантировать отсутствие кэширования (думать о новых версиях в производстве) - это заменить файл js или css номером версии. Я делаю это с помощью веб-пакета.


1

Также вы можете попробовать в вашем серве установить заголовки, например:

...
import {Injectable} из "@ angular / core";
import {HttpClient, HttpHeaders, HttpParams} из "@ angular / common / http";
...
 @Injectable ()
класс экспорта MyService {

    частные заголовки: HttpHeaders;


    конструктор (частный http: HttpClient ..) 
    {


        this.headers = new HttpHeaders ()
                    .append ("Content-Type", "application / json")
                    .append («Принять», «Приложение / JSON»)
                    .append ("LanguageCulture", this.headersLanguage)
                    .append ("Cache-Control", "no-cache")
                    .append ("Pragma", "no-cache")                   
    }
}
....


0

Эта проблема связана с проблемой кэширования IE, как вы сказали, вы можете протестировать ее в режиме отладки IE, нажав клавишу f12 (в режиме отладки это будет нормально работать) .IE не будет принимать данные сервера при каждом вызове страницы, это займет данные из кеша. Чтобы отключить это, выполните одно из следующих действий:

  1. добавьте следующее к URL-адресу запроса на обслуживание http

// До (выдан)

this.httpService.get (this.serviceUrl + "/eAMobileService.svc/ValidateEngagmentName/" + engagementName, {})

// После (работает нормально)

this.httpService.get (this.serviceUrl + "/eAMobileService.svc/ValidateEngagmentName/" + engagementName + "? DateTime =" + new Date (). getTime () + '', {cache: false})

  1. отключить кеш для всего модуля: -

$ httpProvider.defaults.headers.common ['Pragma'] = 'no-cache';


0
meta http-equiv="Cache-Control" content="no-cache"

Я просто добавил это в View, и он начал работать в IE. Подтвердили работу на Angular 2.


0

Одним из вариантов является использование простого подхода - добавление метки времени при каждом запросе без необходимости очищать кэш.

    let c=new Date().getTime();
    $http.get('url?d='+c)

-2

Попробуйте это, у меня получилось в похожем случае: -

$http.get("your api url", {
headers: {
    'If-Modified-Since': '0',
    "Pragma": "no-cache",
    "Expires": -1,
    "Cache-Control": "no-cache, no-store, must-revalidate"
 }
})
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.