我有一个问题,让我的缓存更简单。我认为有更好的方法来做到这一点。我的问题是我必须这样做"缓存"每个get()函数中的代码都会产生更长的代码。有谁帮助如何做到这一点最好的方式?谢谢。这是我的代码,如下所示。我在我的代码中做的是我在news.service.ts中执行get()函数以从http获取数据,并在我的新闻列表中订阅它。
news.service.ts
getAllNews() {
if(this.newslist != null) {
return Observable.of(this.newslist);
}
else {
return this.httpClient
.get('http://sample.com/news')
.map((response => response))
.do(newslist => this.newslist = newslist)
.catch(e => {
if (e.status === 401) {
return Observable.throw('Unauthorized');
}
});
}
}
新闻list.service.ts
this.subscription = this.newsService.getAllNews()
.subscribe(
(data:any) => {
console.log(data);
this.newslists = data.data.data;
},
error => {
this.authService.logout()
this.router.navigate(['signin']);
});
}
答案 0 :(得分:2)
如果您打算使用通用的,可以用于不同的API调用或服务,那么您可以执行以下操作:
import { Injectable } from '@angular/core';
import { HttpClient } from "@angular/common/http";
import { Observable, of } from 'rxjs';
import { map } from 'rxjs/operators';
class CacheItem<T> {
url: string;
timestampCached: number;
data: T;
}
@Injectable({
providedIn: 'root'
})
export class MyCachedHttpClient {
cache: CacheItem<any>[] = [];
constructor(
private http: HttpClient,
) { }
get<T>(url: string, cacheTime?: number, forceRefresh: boolean = false)
: Observable<T> {
let cachedItem: CacheItem<T> = this.getCachedItem<T>(url);
if (cachedItem != undefined && !forceRefresh) {
let expireDate = cachedItem.timestampCached + cacheTime;
if (Date.now() < expireDate) {
return of(cachedItem.data);
}
}
return this.http.get<T>(url).pipe(
map(data => {
if (cacheTime) { // if we actually want to cache the result
if (cachedItem == undefined) {
cachedItem = new CacheItem();
cachedItem.url = url;
this.cache.push(cachedItem);
}
cachedItem.data = data;
cachedItem.timestampCached = Date.now();
}
return data;
})
);
}
private getCachedItem<T>(url: string): CacheItem<T> {
return this.cache.find(item => item.url == url);
}
}
然后在任何地方使用MyCachedHttpClient
代替HttpClient
。
注意:
HttpClient
get()
函数的许多功能的基本实现,因为我没有在此重新实现options
参数。答案 1 :(得分:1)
我不太清楚news.service.ts
和news-list.service.ts
之间的区别是什么,但主要的概念是你需要分开关注点。您可以做的最基本的分离是将“数据提供者”从“数据使用者”中分离出来
这可以是获取和管理数据的任何内容。无论是内存缓存数据,服务调用等。在您的示例中,在我看来news.service.ts
它是与新闻相关的所有内容的Web API客户端/代理。
如果这是一个小文件,您可以将所有与新闻相关的缓存管理移动到此文件或...创建另一个管理缓存和包装news.service.ts
的组件。该组件将从其缓存中提供数据,如果缓存不存在或已过期,则它会调用news.service.ts
方法。这种方式news.service.ts
唯一的责任就是向API发出ajax请求。
这是一个没有承诺,可观察或错误处理的例子,只是为了给你一个想法......
class NewsProvider{
constructor(){
this.newsCache = [];
}
getNewsItemById(id){
const item = this.newsCache.filter((i) => {i.id === id});
if(item.length === 1) return item[0];
this.newsCache = newsService.getAllNews();
item = this.newsCache.filter((i) => {i.id === id});
if(item.length === 1) return item[0];
else return null;
}
}
这些将是需要数据的任何组件,主页中的新闻自动收录器,导航菜单中某处的徽章通知......可能存在需要新闻相关数据的任何组件(或视图)。出于这个原因,这些组件/视图不需要知道数据来自何处。
这些组件将使用“数据提供者”作为主要数据来源
只需要在一个地方管理(并且可以)管理缓存以及与网络相关的操作