$ Http için açısal IE Önbellek sorunu


251

IE'den gönderilen tüm ajax çağrıları Angular tarafından önbelleğe alınır ve 304 responsesonraki tüm çağrılar için bir alırım . İstek aynı olsa da, yanıt benim durumumda aynı olmayacak. Bu önbelleği devre dışı bırakmak istiyorum. cache attribute$ Http.get için eklemeyi denedim ama yine de yardımcı olmadı. Bu sorun nasıl çözülebilir?

Yanıtlar:


439

Her bir GET isteği için önbelleğe almayı devre dışı bırakmak yerine, $ httpProvider'da genel olarak devre dışı bırakıyorum:

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-SinceBaşlık markaları + iisnode atmak üzerinden yüklenen her html dosyası için 400 Bad Request IIS ngIncludeve ngView. Aşağıdaki iki başlık benim için sorunu çözdü (önbelleğe alma sorunu olmayan Chrome'dan çektim): $httpProvider.defaults.headers.get['Cache-Control'] = 'no-cache'; $httpProvider.defaults.headers.get['Pragma'] = 'no-cache';
Langdon

4
Bence bu cevap cevap olarak işaretlenmelidir, Martin tarafından sağlanan çözüm işe yararken, gerçek bir düzeltmeden daha çok bir hack'tir.
Robba

4
Bu, yerel GET isteklerim için çalıştı, ancak GET yöntemi yerine OPTIONS yöntemini kullanmaya başlamak için yaptığım bir CORS isteğine neden oldu. Üçüncü taraf sunucu OPTIONS yöntemini desteklemediğinden, geçici çözümüm bu istekte bulunmak için jQuery.get () yöntemini kullanmak ve yanıt işleyicilerinde $ scope.apply () yöntemini kullanmaktır.
Ben

13
Başlık kullanımı If-Modified-Since = "0"Tomcat'i ( 0Geçerli RFC değeri olmadığı için başlık tarihini ayrıştırmada sorun var ). Mon, 26 Jul 1997 05:00:00 GMTBunun yerine değer kullanılarak düzeltildi .
lopisan

6
"If-Modified-Since" başlığını kullanmadım ve o olmadan çalıştı. Sadece diğer ikisi gerekli.
Michael Mahony

69

Ya da benzersiz bir sorgu dizesi (jQuery cache: false seçeneği ile yaptığı bu olduğuna inanıyorum) ekleyebilirsiniz.

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

Belki de daha iyi bir çözüm, sunucuya erişiminiz varsa, önbelleği önlemek için gerekli başlıkların ayarlandığından emin olabilirsiniz. ASP.NET MVC Bu yanıtı kullanıyorsanız yardımcı olabilir.


2
$http.get(url+ "?"+new Date().toString())parametresini kullanmadan ancak sorgu dizesine eklemeden başka bir gösterimdir.
Davut Gürbüz

28

bir önleme ekleyebilirsiniz.

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

doğruladıktan sonra console.log satırlarını kaldırmalısınız.


Ve $logonları çıkarmayı unutmanız durumunda kullanmalısınız .
Carl G

2
Önemli bölümleri yürütmedi çünkü IE, boş bir sayfaya yol açan ciddi önbellek sorunları yaşıyorum. Sahne önleme aracını kullanmak bu sorunu çözdü! +1
raoulinski

Ek başlıklar eklerseniz, CORS ve IE'nin ön kontrol isteğini tetikleme davranışıyla ilgili sorunları önlediğinden, bu en iyi yaklaşım olduğunu düşünüyorum. Bu, ek sorunlarla karşılaşmamak için en güvenli yöntem gibi görünüyor
chrismarx

@dilip pattnaik: - Neden bu sorun açısal ve yani?
MiHawk

14

Açısal projede index.html dosyasına üç meta etiket ekledim ve IE'de önbellek sorunu çözüldü.

<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.htmlIE11'in AJAX isteklerini önbelleğe aldığını fark ettiğimizde zaten bu meta etiketler vardı : / Ama $httpProviderdiğer cevaplarda gösterildiği gibi yapılandırma iyi çalıştı.
walen

14

Kopyalama başka bir iplik cevabımı .

İçin açısal 2 ve daha yeni , kolay yolu eklemek için no-cachegeçersiz kılarak başlıkları 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'
    });
}

Ve modülünüzde referans verin:

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

Bunlar, tarayıcı yanıtı için değil, sunucu yanıtı için üstbilgiler olmaz mı? ( If-Modified-SinceYukarıdaki yöntemi kullanarak geçmişte bazı tarihlerle ayarlanabileceğini hayal edebiliyordum .)
Arjan

@Vitaliy: - Neden bu sorun açısal ve yani?
Mihawk

Yaklaşımınız zaten var olan tüm özel başlıkları kaldıracaktır. Bu nedenle, yeni bir Başlık nesnesi oluşturmak yerine aşağıdakileri yapın. 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

Çalıştığım garantili olan şu çizgide bir şeydi:

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

Bütün yöntemler için doğru kullanımını garanti etmek amacıyla, yukarıdaki çözümlerden 2 birleştirmek zorunda kaldı, ama sen yerine commonsahip getveya başka bir yöntemle yani put, post, deletefarklı durumlar için bu işi yapmak için.


Bunu angular.js dosyasına kodun içine eklediğinizi söyleyebilir misiniz? hangi satır #?
JonathanScialpi

@JonathanScialpi Nereye koyabileceğimi göstermek için güncelledim. Anonim işlev içinde olduğu yerde önemli değil.
marksyzm

@marksyzm u plzz bana bu çizginin ne anlama geldiğini söyleyebilirif (!$httpProvider.defaults.headers.get) { $httpProvider.defaults.headers.common = {}; }
Monojit Sarkar

@MonojitSarkar Ah, bu üstbilgi olması gerekiyordu. İf deyiminde ortak, bu işaretçi için teşekkürler
marksyzm

1
["If-Modified-Since"] = "0"yasa dışıdır ve bazı arka uçlarda Kötü İstek oluşturur. bir tarih olmalı.
jenson-button-event

8

Bu tek çizgi bana yardımcı oldu (Açısal 1.4.8):

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

UPD: IE11 agresif önbellekleme sorunudur. Fiddler'a bakarken F12 modunda isteklerin "Pragma = no-cache" gönderdiğini ve bir sayfayı her ziyaret ettiğimde bitiş noktasının talep edildiğini fark ettim. Ancak normal modda bitiş noktasını, sayfayı ilk ziyaret ettiğimde yalnızca bir kez istendi.


1
Sadece FYI, bu cevap Azure'un blob deposundan dosya istendiğinde, izlenmesi zor ancak sonunda bunun neden olduğunu anladığında CORS sorununa neden oldu. Pragma başlığını kaldırmak CORS sorunumu düzeltti (ancak IE önbellek sorununu yeniden oluşturdu).
keithl8041

7

Önbelleğe almayı önlemek için bir seçenek, aynı kaynak veya veriler için farklı URL vermektir. Farklı URL oluşturmak için URL'nin sonuna rastgele bir sorgu dizesi ekleyebilirsiniz. Bu teknik JQuery, Angular veya diğer tip ajax isteklerinde işe yarar.

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

6

Ben rastgele bir sayı olarak datetime ekleme çözüldü:

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

: - Neden bu sorun açısal ve örn.
MiHawk

4

Yukarıdaki çözüm işe yarayacaktır (url'yi sorgu dizesine yeni bir parametre ekleyerek benzersiz hale getirin) ama çözüm önerisini [burada] tercih ediyorum: AngularJS'de IE Önbelleğini Önlemenin Daha İyi Yolu?IE'ye özgü olmadığından bunu sunucu düzeyinde işler. Yani, bu kaynak önbelleğe alınmaması gerekiyorsa, sunucuda yapın (kullanılan tarayıcı ile hiçbir ilgisi yoktur; kaynağa ilgi çekicidir).

Örneğin JAX- RS'li java'da JAX-RS v1 için programlı olarak veya JAX-RS v2 için declativly olarak yapın.

Eminim kimse nasıl yapılacağını anlar


1
Her ne kadar detaylandırılabilse de, bunu yapmanın uygun yolu budur. İstemci tarafı neyin önbellekleneceğini veya neyin önlenmeyeceğini seçmemelidir, ancak istemciye neyin önbelleğe alınması gerektiğini belirtmesi gereken sunucu olmalıdır.
Arşimet Trajano

Tamamen katılıyorum, bu uygun bir yol olmalı
smnbbrv

1

Bu biraz eskidir ama: Gibi çözümler kullanılmıyor. Sunucunun önbelleği kullanmasına izin verin (yanıtta). Önbelleğe almayı (üretimdeki yeni sürümleri düşünerek) garanti etmenin tek yolu, js veya css dosyasını sürüm numarasıyla değiştirmektir. Bunu webpack ile yapıyorum.


1

ayrıca örneğin başlıkları ayarlamak için hizmetinizde deneyebilirsiniz:

...
{Enjeksiyonluk} 'u "@ açısal / çekirdek" ten içe aktarın;
{@ angular / common / http "den {HttpClient, HttpHeaders, HttpParams} 'ı içe aktarın;
...
 @Injectable ()
ihracat sınıfı MyService {

    özel başlıklar: HttpHeaders;


    yapıcı (özel http: HttpClient ..) 
    {


        this.headers = yeni HttpHeaders ()
                    .append ("İçerik Türü", "uygulama / json")
                    .append ("Kabul et", "uygulama / json")
                    .append ("Dil Kültürü", this.headersLanguage)
                    .append ("Önbellek Denetimi", "önbellek yok")
                    .append ("Pragma", "önbellek yok")                   
    }
}
....


0

Bu sorun, söylediğiniz gibi IE önbellek sorunundan kaynaklanmaktadır, f12 tuşuna basarak IE hata ayıklama modunda test edebilirsiniz (bu hata ayıklama modunda iyi çalışır). Sayfa her aradığında sunucu verilerini almayacak, alır önbellekteki veriler. Bunu devre dışı bırakmak için aşağıdakilerden birini yapın:

  1. http hizmet isteği URL'nizle aşağıdakileri ekleyin

// Önce (bir tane çıkarılmış)

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

// Sonra (iyi çalışıyor)

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

  1. tüm Modül için önbelleği devre dışı bırak: -

$ httpProvider.defaults.headers.common ['Pragma'] = 'önbellek yok';


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

Ben sadece View için ekledi ve IE üzerinde çalışmaya başladı. Açısal 2 üzerinde çalıştığı onaylandı.


0

Bir seçenek, önbelleği temizlemeye gerek olmayan her istekle birlikte Zaman Damgası ekleme basit yaklaşımını kullanmaktır.

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

-2

Bunu deneyin, benzer bir durumda benim için çalıştı: -

$http.get("your api url", {
headers: {
    'If-Modified-Since': '0',
    "Pragma": "no-cache",
    "Expires": -1,
    "Cache-Control": "no-cache, no-store, must-revalidate"
 }
})
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.