Кутове видання 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.