Кутове видання IE-кешування для $ http


251

Усі дзвінки ajax, що надсилаються з IE, кешуються Angular, і я отримую 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';
Ленґдон,

4
На мою думку, цю відповідь слід позначати як відповідь, хоча рішення, яке надає Мартін, дійсно працює, це скоріше хак, ніж фактичне виправлення.
Робба

4
Це працювало для моїх локальних запитів GET, але це викликало один запит CORS, який я робив, щоб почати використовувати метод OPTIONS замість методу GET. Сторонній сервер не підтримує метод OPTIONS, тому моєму вирішенню є використання jQuery.get () для створення цього запиту та використання $ range.apply () в обробниках відповідей.
Бен

13
Використання If-Modified-Since = "0"заголовка розбиває Tomcat (Проблема з розбором дати заголовка, оскільки 0не є дійсним значенням RFC ). Виправлено за допомогою значення Mon, 26 Jul 1997 05:00:00 GMT.
lopisan

6
Я не використовував заголовок "If-Modified-Since", і він працював без цього. Просто два інших потрібні.
Майкл Махоні

69

Ви можете або додати унікальний запит (я вважаю, що це jQuery робить із кешем: помилковий варіант) до запиту.

$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
raoulinski

Я думаю, що це найкращий підхід, оскільки він дозволяє уникнути проблем із поведінкою 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дату, яка була далекою в минулому, використовуючи вищевказаний метод.)
Ар'ян

@ Віталій: - Чому ця проблема виникає з кутовим, тобто?
MiHawk

Ваш підхід видалить будь-які власні заголовки, які вже є. Отже, виконайте наступне замість створення нового об’єкта заголовка. headers: req.headers .set('Cache-Control', 'no-cache') .set('Pragma', 'no-cache') .set('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT')
Chamika Goonetilaka

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 Я оновив його, щоб показати, де я міг би поставити його. Де він знаходиться в межах анонімної функції не має значення.
markyzm

@marksyzm можеш у плзз сказати мені, у чому сенс цього рядкаif (!$httpProvider.defaults.headers.get) { $httpProvider.defaults.headers.common = {}; }
Monojit Sarkar

@MonojitSarkar Ах, це повинно бути headers.common у заяві if, спасибі за цей покажчик
marksyzm

1
["If-Modified-Since"] = "0"є незаконним та створює поганий запит на деяких задніх кінцях. це має бути дата.
jenson-button-event

8

Цей єдиний рядок допоміг мені (кутовий 1.4.8):

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

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


1
Щойно FYI, ця відповідь спричинила проблему CORS під час запиту файлів із сховища блоку 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 з номером версії. Я роблю це за допомогою webpack.


1

також ви можете спробувати у своєму сервісі встановити заголовки типу:

...
імпорт {Injectable} з "@ angular / core";
імпортувати {HttpClient, HttpHeaders, HttpParams} з "@ angular / common / http";
...
 @Injectable ()
експортний клас MyService {

    приватні заголовки: HttpHeaders;


    конструктор (приватний http: HttpClient ..) 
    {


        this.headers = нові HttpHeaders ()
                    .append ("Тип вмісту", "додаток / json")
                    .append ("Прийняти", "application / json")
                    .append ("LanguageCulture", this.headersLanguage)
                    .append ("Кеш-контроль", "без кешу")
                    .append ("Прагма", "без кешу")                   
    }
}
….


0

Ця проблема пов'язана з проблемою кешування IE, як ви сказали, ви можете протестувати її в режимі налагодження IE, натиснувши f12 (це буде добре працювати в режимі налагодження) .IE не буде приймати дані сервера щоразу, коли сторінка дзвонить, це займе дані з кешу. Щоб вимкнути це, виконайте одну з наступних дій:

  1. додайте наступне до URL-адреси запиту служби http

// Раніше (видав)

this.httpService.get (this.serviceUrl + "/eAMobileService.svc/ValidateEngagmentName/" + присвоєння імені, {})

// Після (добре працює)

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

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

$ httpProvider.defaults.headers.common ['Pragma'] = 'без кешу';


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

Я щойно додав це до View, і він почав працювати над IE. Підтверджено для роботи над кутовим 2.


0

Варіант полягає у використанні простого підходу додавання Timestamp до кожного запиту, не потрібно очищати кеш.

    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.