防止 IE11 在 Angular 中缓存 GET 调用 2
Prevent IE11 caching GET call in Angular 2
我有一个休息端点,returns 一个 GET 调用列表。我还有一个 POST 端点来添加新项目和一个 DELETE 来删除它们。这在 Firefox 和 Chrome 中有效,POST 和 DELETE 在 IE11 中有效。但是,IE11 中的 GET 仅适用于页面的初始加载。正在刷新 returns 缓存数据。我在 Angular 1 中看到了 post 有关此行为的信息,但在 Angular 2(候选发布版本 1)中没有任何内容。
转发 Whosebug 响应 Angular IE Caching issue for $http,您应该将 headers 'Pragma'、'no-cache'、'If-Modified-Since' 添加到每个 'GET' 请求。
angular2 不再支持拦截器方案。所以你应该按照这里描述的那样扩展 http What is httpinterceptor equivalent in angular2?。
Angular 4.3 现在包含支持拦截器的 HttpClient 服务。
有点晚了,不过我运行陷入了同样的问题。对于 Angular 4.X 我写了一个自定义的 Http class 以在末尾附加一个 运行dom 数字以防止被 IE 缓存。它基于 dimeros () 的第二个 link。 警告:不保证运行100% 没有错误。
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Http, Response, XHRBackend, RequestOptions, RequestOptionsArgs,
URLSearchParams } from '@angular/http';
@Injectable()
export class NoCacheHttp extends Http {
constructor(backend: XHRBackend, options: RequestOptions) {
super(backend, options);
}
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
//make options object if none.
if (!options) {
options = { params: new URLSearchParams() };
}
//for each possible params type, append a random number to query to force no browser caching.
//if string
if (typeof options.params === 'string') {
let params = new URLSearchParams(options.params);
params.set("k", new Date().getTime().toString());
options.params = params;
//if URLSearchParams
} else if (options.params instanceof URLSearchParams) {
let params = <URLSearchParams>options.params;
params.set("k", new Date().getTime().toString());
//if plain object.
} else {
let params = options.params;
params["k"] = new Date().getTime().toString();
}
return super.get(url, options);
}
}
对于 Angular 2 和更高版本,通过覆盖 RequestOptions
添加 no-cache headers 的最简单方法:
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 }
]
})
今天,我也遇到了这个问题,(该死的IE)。
在我的项目中,我使用 httpclient
,而没有使用 BaseRequestOptions
。
我们应该用Http_Interceptor
来解决!
import { HttpHandler,
HttpProgressEvent,
HttpInterceptor,
HttpSentEvent,
HttpHeaderResponse,
HttpUserEvent,
HttpRequest,
HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
export class CustomHttpInterceptorService implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler):
Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
const nextReq = req.clone({
headers: req.headers.set('Cache-Control', 'no-cache')
.set('Pragma', 'no-cache')
.set('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT')
.set('If-Modified-Since', '0')
});
return next.handle(nextReq);
}
}
模块提供
@NgModule({
...
providers: [
...
{ provide: HTTP_INTERCEPTORS, useClass: CustomHttpInterceptorService, multi: true }
]
})
使用元 HTML 标签禁用浏览器缓存:-
<meta http-equiv="cache-control" content="no-cache, must-revalidate, post-check=0, pre-check=0">
<meta http-equiv="expires" content="0">
<meta http-equiv="pragma" content="no-cache">
编辑:请参阅下面的评论 - 这不是必需的(在绝大多数情况下)。
扩展 Jimmy Ho 上面的回答,我只想防止缓存我的 API 调用,而不是其他将从缓存中受益的静态内容。我的所有 API 调用都是对包含“/api/”的 URL 的调用,所以我修改了 Jimmy Ho 的代码,检查只添加缓存 headers 如果请求 URL 包含“/api/”:
import { HttpHandler,
HttpProgressEvent,
HttpInterceptor,
HttpSentEvent,
HttpHeaderResponse,
HttpUserEvent,
HttpRequest,
HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
export class CustomHttpInterceptorService implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler):
Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
// Only turn off caching for API calls to the server.
if (req.url.indexOf('/api/') >= 0) {
const nextReq = req.clone({
headers: req.headers.set('Cache-Control', 'no-cache')
.set('Pragma', 'no-cache')
.set('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT')
.set('If-Modified-Since', '0')
});
return next.handle(nextReq);
} else {
// Pass the request through unchanged.
return next.handle(req);
}
}
}
正如上面的回答,您可以使用http请求拦截器修改或设置一个新的header请求。
下面是在 angular 版本的 http 请求拦截器上设置 headers 的更简单的方法(Angular 4+).这种方法只会设置或更新某个请求 header。这是为了避免删除或覆盖一些重要的 header,例如授权 header。
// cache-interceptor.service.ts
import { Injectable } from '@angular/core';
import {
HttpInterceptor,
HttpRequest,
HttpHandler,
} from '@angular/common/http';
@Injectable()
export class CacheInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler) {
const httpRequest = req.clone({
headers: req.headers
.set('Cache-Control', 'no-cache')
.set('Pragma', 'no-cache')
.set('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT')
})
return next.handle(httpRequest)
}
}
// app.module.ts
import { HTTP_INTERCEPTORS } from '@angular/common/http'
import { CacheInterceptor } from './cache-interceptor.service';
// on providers
providers: [{ provide: HTTP_INTERCEPTORS, useClass: CacheInterceptor, multi: true }]
我有一个休息端点,returns 一个 GET 调用列表。我还有一个 POST 端点来添加新项目和一个 DELETE 来删除它们。这在 Firefox 和 Chrome 中有效,POST 和 DELETE 在 IE11 中有效。但是,IE11 中的 GET 仅适用于页面的初始加载。正在刷新 returns 缓存数据。我在 Angular 1 中看到了 post 有关此行为的信息,但在 Angular 2(候选发布版本 1)中没有任何内容。
转发 Whosebug 响应 Angular IE Caching issue for $http,您应该将 headers 'Pragma'、'no-cache'、'If-Modified-Since' 添加到每个 'GET' 请求。
angular2 不再支持拦截器方案。所以你应该按照这里描述的那样扩展 http What is httpinterceptor equivalent in angular2?。
Angular 4.3 现在包含支持拦截器的 HttpClient 服务。
有点晚了,不过我运行陷入了同样的问题。对于 Angular 4.X 我写了一个自定义的 Http class 以在末尾附加一个 运行dom 数字以防止被 IE 缓存。它基于 dimeros (
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { Http, Response, XHRBackend, RequestOptions, RequestOptionsArgs,
URLSearchParams } from '@angular/http';
@Injectable()
export class NoCacheHttp extends Http {
constructor(backend: XHRBackend, options: RequestOptions) {
super(backend, options);
}
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
//make options object if none.
if (!options) {
options = { params: new URLSearchParams() };
}
//for each possible params type, append a random number to query to force no browser caching.
//if string
if (typeof options.params === 'string') {
let params = new URLSearchParams(options.params);
params.set("k", new Date().getTime().toString());
options.params = params;
//if URLSearchParams
} else if (options.params instanceof URLSearchParams) {
let params = <URLSearchParams>options.params;
params.set("k", new Date().getTime().toString());
//if plain object.
} else {
let params = options.params;
params["k"] = new Date().getTime().toString();
}
return super.get(url, options);
}
}
对于 Angular 2 和更高版本,通过覆盖 RequestOptions
添加 no-cache headers 的最简单方法:
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 }
]
})
今天,我也遇到了这个问题,(该死的IE)。
在我的项目中,我使用 httpclient
,而没有使用 BaseRequestOptions
。
我们应该用Http_Interceptor
来解决!
import { HttpHandler,
HttpProgressEvent,
HttpInterceptor,
HttpSentEvent,
HttpHeaderResponse,
HttpUserEvent,
HttpRequest,
HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
export class CustomHttpInterceptorService implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler):
Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
const nextReq = req.clone({
headers: req.headers.set('Cache-Control', 'no-cache')
.set('Pragma', 'no-cache')
.set('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT')
.set('If-Modified-Since', '0')
});
return next.handle(nextReq);
}
}
模块提供
@NgModule({
...
providers: [
...
{ provide: HTTP_INTERCEPTORS, useClass: CustomHttpInterceptorService, multi: true }
]
})
使用元 HTML 标签禁用浏览器缓存:-
<meta http-equiv="cache-control" content="no-cache, must-revalidate, post-check=0, pre-check=0">
<meta http-equiv="expires" content="0">
<meta http-equiv="pragma" content="no-cache">
编辑:请参阅下面的评论 - 这不是必需的(在绝大多数情况下)。
扩展 Jimmy Ho 上面的回答,我只想防止缓存我的 API 调用,而不是其他将从缓存中受益的静态内容。我的所有 API 调用都是对包含“/api/”的 URL 的调用,所以我修改了 Jimmy Ho 的代码,检查只添加缓存 headers 如果请求 URL 包含“/api/”:
import { HttpHandler,
HttpProgressEvent,
HttpInterceptor,
HttpSentEvent,
HttpHeaderResponse,
HttpUserEvent,
HttpRequest,
HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
export class CustomHttpInterceptorService implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler):
Observable<HttpSentEvent | HttpHeaderResponse | HttpProgressEvent | HttpResponse<any> | HttpUserEvent<any>> {
// Only turn off caching for API calls to the server.
if (req.url.indexOf('/api/') >= 0) {
const nextReq = req.clone({
headers: req.headers.set('Cache-Control', 'no-cache')
.set('Pragma', 'no-cache')
.set('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT')
.set('If-Modified-Since', '0')
});
return next.handle(nextReq);
} else {
// Pass the request through unchanged.
return next.handle(req);
}
}
}
正如上面的回答,您可以使用http请求拦截器修改或设置一个新的header请求。 下面是在 angular 版本的 http 请求拦截器上设置 headers 的更简单的方法(Angular 4+).这种方法只会设置或更新某个请求 header。这是为了避免删除或覆盖一些重要的 header,例如授权 header。
// cache-interceptor.service.ts
import { Injectable } from '@angular/core';
import {
HttpInterceptor,
HttpRequest,
HttpHandler,
} from '@angular/common/http';
@Injectable()
export class CacheInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler) {
const httpRequest = req.clone({
headers: req.headers
.set('Cache-Control', 'no-cache')
.set('Pragma', 'no-cache')
.set('Expires', 'Sat, 01 Jan 2000 00:00:00 GMT')
})
return next.handle(httpRequest)
}
}
// app.module.ts
import { HTTP_INTERCEPTORS } from '@angular/common/http'
import { CacheInterceptor } from './cache-interceptor.service';
// on providers
providers: [{ provide: HTTP_INTERCEPTORS, useClass: CacheInterceptor, multi: true }]