Javascript 防止 IE11 在 Angular 2 中缓存 GET 调用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37755782/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 20:41:58  来源:igfitidea点击:

Prevent IE11 caching GET call in Angular 2

javascriptangulartypescriptinternet-explorer-11http-caching

提问by cmaynard

I have a rest endpoint that returns a list on a GET call. I also have a POST endpoint to add new items and a DELETE to remove them. This works in Firefox and Chrome, and the POST and DELETE work in IE11. However, the GET in IE11 only works on initial load of the page. Refreshing returns cached data. I have seen post about this behavior in Angular 1 but nothing for Angular 2(release candidate 1).

我有一个休息端点,它在 GET 调用中返回一个列表。我还有一个 POST 端点来添加新项目和一个 DELETE 来删除它们。这在 Firefox 和 Chrome 中有效,POST 和 DELETE 在 IE11 中有效。但是,IE11 中的 GET 仅适用于页面的初始加载。刷新返回缓存数据。我在 Angular 1 中看到过关于这种行为的帖子,但在 Angular 2(候选发布版 1)中没有看到。

采纳答案by Jimmy Ho

Today, I also had this problem, (damn IE). In my project, I use httpclient, that hasn't BaseRequestOptions. We should use Http_Interceptorto resolve it!

今天,我也遇到了这个问题,(该死的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);
  }
}

Module provide

模块提供

@NgModule({
    ...
    providers: [
        ...
        { provide: HTTP_INTERCEPTORS, useClass: CustomHttpInterceptorService, multi: true }
    ]
})

回答by Vitaliy Ulantikov

For Angular 2 and newer, the easiest way to add no-cache headers by overriding RequestOptions:

对于Angular 2 和更新版本,通过覆盖来添加无缓存标头的最简单方法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'
    });
}

Module:

模块:

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

回答by dimeros

Forward the stackoverflow response Angular IE Caching issue for $http, you should add the headers 'Pragma', 'no-cache', 'If-Modified-Since' to each 'GET' request.

转发$http的 stackoverflow 响应Angular IE 缓存问题,您应该将标头“Pragma”、“no-cache”、“If-Modified-Since”添加到每个“GET”请求。

The interceptor's scenario is not supported to angular 2 anymore. So you should extend the http as it is described here What is httpinterceptor equivalent in angular2?.

拦截器的场景不再支持 angular 2。所以你应该像这里描述的那样扩展 http什么是 angular2 中的 httpinterceptor 等价物?.

Angular 4.3 now includes the HttpClientservice, which supports interceptors.

Angular 4.3 现在包含支持拦截器的HttpClient服务。

回答by AndrWeisR

Edit: See comment below - this is not necessary (in the vast majority of cases).

编辑:请参阅下面的评论 - 这不是必需的(在绝大多数情况下)。

Expanding on Jimmy Ho's answer above, I only want to prevent caching of my API calls, and not other static content which will benefit from being cached. All of my API calls are to URLs that contain "/api/", so I amended Jimmy Ho's code with a check that only adds the cache headers if the requested URL contains "/api/":

扩展上面 Jimmy Ho 的回答,我只想防止缓存我的 API 调用,而不是其他将从缓存中受益的静态内容。我所有的 API 调用都是针对包含“/api/”的 URL,所以我修改了 Jimmy Ho 的代码,检查只在请求的 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);
    }
}

}

}

回答by John Wilfred

As answered above, you can use http request interceptor to modify or set a new header on the request. Below is a much simpler way of setting headers on http request interceptor for Later angular versions(Angular 4+). This approach would only set or update a certain request header. This is to avoid removing or overriding some important headers like the authorization header.

如上所述,您可以使用 http 请求拦截器来修改或设置请求的新标头。下面是一种在 http 请求拦截器上为更高版本的Angular版本(Angular 4+)设置标头的更简单的方法。这种做法只会设置或更新某个请求头。这是为了避免删除或覆盖一些重要的标头,如授权标头。

// 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 }]

回答by Manzer

Disable browser caching with meta HTML tags:-

使用元 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">

回答by Chris Moore

A little late, but I ran into the same problem. For Angular 4.XI wrote a custom Http class to append a random number to the end to prevent caching by IE. It is based on the 2nd link by dimeros (What is httpinterceptor equivalent in angular2?). Warning: not guaranteed to be 100% bug free.

有点晚了,但我遇到了同样的问题。对于Angular 4.X,我编写了一个自定义 Http 类来在末尾附加一个随机数以防止 IE 缓存。它基于 dimeros 的第二个链接(angular2中的 httpinterceptor 等价物是什么?)。警告:不能保证 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);
    }
}