angular - Angular Caching 通过拦截器变得简单,但不是针对每个请求,仅通过布尔值
问题描述
希望通过拦截器缓存请求,但不是针对每个请求。我需要一个标志来希望能够缓存与否
解决方案
使用拦截器在 Angular 中实现缓存仅针对少数请求,而不是通过布尔值有条件地执行每个请求。
我一直在检查有关仅缓存少数请求而不是全部请求的在线解决方案。可悲的是,没有任何适合此目的的解决方案。因此,我决定编写一种非常简单的缓存方法来缓存特定请求。
这可以通过以下方式完成:
如下创建一个 cache.interceptor & cache.service 并将其添加到 app.module 的提供者中,如下所示:
providers:[
CacheService,
{ provide: HTTP_INTERCEPTORS, useClass: CachingInterceptor, multi: true }]
CachingInterceptor 代码:拦截器只会在它看到由进行 http 调用的服务设置的特定标头('cache-response')时缓存请求。
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Observable';
// Add the service we created in Step 1
import { of } from 'rxjs';
import { tap } from 'rxjs/operators';
import { CacheService } from './cache.service';
@Injectable()
export class CachingInterceptor implements HttpInterceptor {
constructor(private readonly cacheService: CacheService) {
}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
// Don't cache if it's not a GET request
if (req.method !== 'GET') {
return next.handle(req);
}
// delete cache if no header is set by service's method
if (!req.headers.get('cache-response')) {
if (this.cacheService.cacheMap.get(req.urlWithParams)) {
this.cacheService.cacheMap.delete(req.urlWithParams);
}
return next.handle(req);
}
// Checked if there is cached data for this URI
const cachedResponse = this.cacheService.getFromCache(req);
if (cachedResponse) {
// In case of parallel requests to same URI,
// return the request already in progress
// otherwise return the last cached data
return (cachedResponse instanceof Observable) ? cachedResponse : of(cachedResponse.clone());
}
// If the request of going through for first time
// then let the request proceed and cache the response
return next.handle(req)
.pipe(tap(event => {
if (event instanceof HttpResponse) {
this.cacheService.addToCache(req, event);
}
}));
}
}
CacheService 代码:此服务用于添加/从缓存中获取。
import { HttpRequest, HttpResponse } from '@angular/common/http';
import { Injectable } from '@angular/core';
@Injectable()
export class CacheService {
cacheMap = new Map<any, any>(null);
getFromCache(req: HttpRequest<any>): HttpResponse<any> | undefined {
const url = req.urlWithParams;
const cached = this.cacheMap.get(url);
if (!cached) {
return undefined;
}
return (this.cacheMap.get(url)).response;
}
addToCache(req: HttpRequest<any>, response: HttpResponse<any>): void {
const url = req.url;
const entry = { url, response, addedTime: Date.now() };
this.cacheMap.set(url, entry);
}
}
在您的服务中:
getMethod(int param1, cache = false): any {
let headers: HttpHeaders;
if (cache) {
headers = new HttpHeaders({ 'cache-response': 'true' });
}
return this.http.get(
'http://apiUrl',
{ headers }
);
}
就是这样。您有一个拦截器,它只缓存具有标头集的请求。
推荐阅读
- android - 如何在 Android NDK c++ 上执行 ASE-256-CBC 加密和解密?
- pentaho - 继承数据集会减慢 Pentaho 报表设计器的速度吗?
- apache - geoserver 和 apache:如何将 url 缩减为仅主机名并分别从 url 的路径中删除 /geoserver/?
- python-3.x - 如何在没有第三方或 docker 的情况下在 Windows 上构建 jupyter hub?
- javascript - Sequelize - 使用“Op.or”构建动态 where 子句
- r - 无法导出绘图:R 代码执行错误/无法启动 png() 设备
- javascript - 录制语音消息 - javascript
- javascript - 如何使用 JavaScript 将伪元素直接设置为 html
- mysql - 如何查找捐助者姓名及其一年的捐款总额,包括 ID 为 NULL 的匿名捐助者
- python-3.x - 如何在 MacOS 上安装 PyQt5?