Masalah Caching IE sudut untuk $ http

251

Semua panggilan ajax yang dikirim dari IE di-cache oleh Angular dan saya mendapatkan 304 responseuntuk semua panggilan berikutnya. Meskipun permintaannya sama, responsnya tidak akan sama dalam kasus saya. Saya ingin menonaktifkan cache ini. Saya mencoba menambahkan cache attributeke $ http.get tapi tetap saja tidak membantu. Bagaimana mengatasi masalah ini?

Rahul
sumber

Jawaban:

439

Alih-alih menonaktifkan caching untuk setiap permintaan GET, saya menonaktifkannya secara global di $ 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';
}]);
cnmuc
sumber
78
The If-Modified-Sincemerek sundulan IIS + iisnode lemparan 400 Bad Request untuk setiap file html dimuat melalui ngIncludedan ngView. Dua header berikut memperbaiki masalah untuk saya (saya menarik mereka dari Chrome, yang tidak memiliki masalah caching): $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache'; $httpProvider.defaults.headers.get['Pragma'] = 'no-cache';
Langdon
4
Menurut pendapat saya, jawaban ini harus ditandai sebagai jawaban, sementara solusi yang diberikan oleh Martin berhasil, itu lebih merupakan peretasan daripada perbaikan yang sebenarnya.
Robba
4
Ini berfungsi untuk permintaan GET lokal saya, tetapi menyebabkan satu permintaan CORS yang saya buat untuk mulai menggunakan metode OPSI alih-alih metode GET. Server pihak ke-3 tidak mendukung metode OPSI, jadi solusi saya adalah menggunakan jQuery.get () untuk membuat permintaan itu dan menggunakan $ scope.apply () di penangan respons.
Ben
13
Penggunaan If-Modified-Since = "0"header merusak Tomcat (Masalah dengan tanggal header parsing, karena 0bukan nilai RFC yang valid ). Tetap menggunakan nilai Mon, 26 Jul 1997 05:00:00 GMTsaja.
lopisan
6
Saya tidak menggunakan header "If-Modified-Sejak" dan itu berhasil tanpa itu. Hanya dua lainnya yang diperlukan.
Michael Mahony
69

Anda dapat menambahkan querystring unik (saya percaya ini adalah apa yang jQuery lakukan dengan cache: opsi salah) pada permintaan.

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

Solusi yang mungkin lebih baik adalah jika Anda memiliki akses ke server, maka Anda dapat memastikan bahwa header yang diperlukan diatur untuk mencegah caching. Jika Anda menggunakan ASP.NET MVC jawaban ini mungkin bisa membantu.

Martin
sumber
2
$http.get(url+ "?"+new Date().toString())hanyalah representasi lain, tanpa menggunakan parameter tetapi menambahkannya ke string kueri.
Davut Gürbüz
28

Anda dapat menambahkan interseptor.

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

Anda harus menghapus baris console.log setelah memverifikasi.

dillip pattnaik
sumber
Dan Anda harus menggunakan $logjika Anda lupa mengeluarkannya.
Carl G
2
Saya mengalami masalah caching serius di IE, yang mengarah ke halaman kosong, karena bagian-bagian penting tidak dieksekusi. Menggunakan pencegat yang disangga memecahkan masalah ini! +1
raoulinski
Saya pikir ini adalah pendekatan terbaik, karena itu menghindari masalah dengan perilaku CORS dan IE memicu permintaan preflight jika Anda menambahkan header tambahan. Ini tampaknya menjadi metode teraman untuk tidak mengalami masalah tambahan
chrismarx
@dilip pattnaik: - Mengapa masalah ini terjadi dengan angular dan ie?
MiHawk
14

Saya hanya menambahkan tiga meta tag ke index.html pada proyek sudut, dan masalah cache diselesaikan di 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">
rtato
sumber
2
Kami sudah memiliki tag meta di kami index.htmlketika kami melihat IE11 sedang caching permintaan AJAX: / ​​Tapi mengkonfigurasi $httpProviderseperti yang ditunjukkan dalam jawaban lain berfungsi dengan baik.
walen
14

Menggandakan jawaban saya di utas lain .

Untuk Angular 2 dan yang lebih baru , cara termudah untuk menambahkan no-cacheheader dengan menimpa 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'
    });
}

Dan rujuk dalam modul Anda:

@NgModule({
    ...
    providers: [
        ...
        { provide: RequestOptions, useClass: CustomRequestOptions }
    ]
})
Vitaliy Ulantikov
sumber
Bukankah itu header untuk respons server, bukan untuk permintaan browser? (Saya bisa membayangkan seseorang dapat menetapkan If-Modified-Sincetanggal yang jauh di masa lalu menggunakan metode di atas.)
Arjan
@Vitaliy: - Mengapa masalah ini terjadi dengan angular dan ie?
MiHawk
Pendekatan Anda akan menghapus semua header kustom yang sudah ada. Oleh karena itu lakukan hal berikut alih-alih membuat objek Header baru. 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

Yang dijamin bahwa saya telah bekerja adalah sesuatu seperti ini:

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

Aku harus menggabungkan 2 dari solusi di atas untuk menjamin pemakaian yang benar untuk semua metode, tetapi Anda dapat mengganti commondengan getatau metode yaitu lainnya put, post, deleteuntuk membuat karya ini untuk kasus yang berbeda.

markyzm
sumber
dapatkah Anda memberi tahu saya di mana dalam kode yang telah Anda tambahkan ini ke file angular.js? baris apa #?
JonathanScialpi
@ JonathanScialpi Saya memperbaruinya untuk menunjukkan di mana saya bisa meletakkannya. Di mana ia berada dalam fungsi anonim seharusnya tidak masalah.
markyzm
@marksyzm dapatkah Anda memberi tahu saya apa arti baris iniif (!$httpProvider.defaults.headers.get) { $httpProvider.defaults.headers.common = {}; }
Monojit Sarkar
@MonojitSarkar Ah, yang seharusnya menjadi headers.common dalam pernyataan if, terima kasih untuk pointer itu
marksyzm
1
["If-Modified-Since"] = "0"adalah ilegal dan dengan menghasilkan Permintaan Buruk pada beberapa bagian belakang. itu harus kencan.
jenson-button-event
8

Baris ini hanya membantu saya (Angular 1.4.8):

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

UPD: Masalahnya adalah IE11 melakukan caching yang agresif. Ketika saya melihat ke Fiddler saya perhatikan bahwa dalam mode F12 permintaan mengirim "Pragma = no-cache" dan titik akhir diminta setiap kali saya mengunjungi halaman. Tetapi dalam mode normal titik akhir diminta hanya sekali pada saat pertama kali ketika saya mengunjungi halaman.

yamaxim
sumber
1
Hanya FYI, jawaban ini menyebabkan masalah CORS ketika meminta file dari penyimpanan gumpalan Azure, sulit dilacak tetapi akhirnya tahu inilah penyebabnya. Menghapus tajuk pragma memperbaiki masalah CORS saya (tetapi menginstal ulang masalah caching IE).
keithl8041
7

Untuk menghindari caching, satu opsi adalah memberikan URL yang berbeda untuk sumber daya atau data yang sama. Untuk menghasilkan URL yang berbeda, Anda dapat menambahkan string kueri acak ke akhir URL. Teknik ini berfungsi untuk permintaan JQuery, Angular atau jenis ajax lainnya.

myURL = myURL +"?random="+new Date().getTime();
Razan Paul
sumber
6

Saya mendapatkannya diselesaikan menambahkan datetime sebagai angka acak:

$http.get("/your_url?rnd="+new Date().getTime()).success(function(data, status, headers, config) {
    console.log('your get response is new!!!');
});
khichar.anil
sumber
: - Mengapa masalah ini terjadi dengan sudut dan yaitu?
MiHawk
4

Solusi di atas akan bekerja (buat url unik dengan menambahkan querystring param baru) tetapi saya lebih suka solusi yang diajukan [di sini]: Cara yang Lebih Baik untuk Mencegah Cache IE di AngularJS? , yang menangani ini di tingkat server karena tidak spesifik untuk IE. Maksud saya, jika sumber daya itu tidak perlu di-cache, lakukan di server (ini karena tidak ada hubungannya dengan browser yang digunakan; itu tidak sesuai dengan sumber daya).

Sebagai contoh di java dengan JAX-RS melakukannya secara programatik untuk JAX-RS v1 atau declativly untuk JAX-RS v2.

Saya yakin siapa pun akan mengetahui cara melakukannya

rguitter
sumber
1
Meskipun dapat dielaborasi, ini adalah cara yang tepat untuk melakukannya. Sisi klien tidak boleh memilih apa yang akan di-cache atau tidak, tetapi haruslah server yang harus memberi tahu klien apa yang perlu di-cache atau tidak.
Archimedes Trajano
Saya sepenuhnya setuju, ini harus menjadi cara yang tepat
smnbbrv
1

Ini agak tua tapi: Solusi seperti sudah usang. Biarkan server menangani cache atau tidak cache (dalam respons). Satu-satunya cara untuk menjamin tidak ada caching (memikirkan versi baru dalam produksi) adalah mengubah file js atau css dengan nomor versi. Saya melakukan ini dengan webpack.

Jens Alenius
sumber
1

Anda juga dapat mencoba di servce Anda untuk mengatur header seperti misalnya:

...
import {Injectable} dari "@ angular / core";
import {HttpClient, HttpHeaders, HttpParams} dari "@ angular / common / http";
...
 @Injectable ()
kelas ekspor MyService {

    header pribadi: HttpHeaders;


    constructor (http pribadi: HttpClient ..) 
    {


        this.headers = HttpHeaders baru ()
                    .append ("Tipe Konten", "aplikasi / json")
                    .append ("Terima", "aplikasi / json")
                    .append ("LanguageCulture", this.headersLanguage)
                    .append ("Kontrol Cache", "no-cache")
                    .append ("Pragma", "no-cache")                   
    }
}
....
Tanpa nama
sumber
0

Masalah ini disebabkan oleh masalah caching IE seperti yang Anda katakan, Anda dapat mengujinya dalam mode debug IE dengan menekan f12 (ini akan berfungsi dengan baik dalam mode debug) .IE tidak akan mengambil data server setiap kali panggilan halaman, dibutuhkan data dari cache. Untuk menonaktifkan ini lakukan salah satu dari yang berikut:

  1. tambahkan berikut ini dengan url permintaan layanan http Anda

// Sebelum (dikeluarkan satu)

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

// Setelah (bekerja dengan baik)

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

  1. nonaktifkan cache untuk seluruh Modul: -

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

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

Saya baru saja menambahkan ini ke View dan mulai bekerja pada IE. Dikonfirmasi untuk bekerja pada Angular 2.

Bir jahe
sumber
0

Sebuah opsi adalah menggunakan pendekatan sederhana untuk menambahkan Stempel Waktu dengan setiap permintaan tidak perlu menghapus cache.

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

Coba ini, itu bekerja untuk saya dalam kasus serupa: -

$http.get("your api url", {
headers: {
    'If-Modified-Since': '0',
    "Pragma": "no-cache",
    "Expires": -1,
    "Cache-Control": "no-cache, no-store, must-revalidate"
 }
})
Mayank Parnami
sumber