ich habe ein Problem damit, das Caching einfacher zu gestalten. Ich denke, dass es einen besseren Weg gibt, dies zu tun. Mein Problem ist, dass ich diese "Zwischenspeicherung" von Codes in jeder get () - Funktion ausführen muss, was zu längeren Codes führt. Hilft jemand, wie man das am besten macht? Vielen Dank. Hier sind meine Codes unten. Was ich in meinen Codes getan habe, ist, dass ich die get () - Funktion in meinem news.service.ts mache, um Daten vom http zu erhalten, und ich abonniere sie in meiner Newsliste.
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');
}
});
}
}
news-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']);
});
}
Wenn Sie etwas generisches haben wollten, das Sie für verschiedene API-Aufrufe oder -Dienste verwenden können, können Sie Folgendes tun:
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);
}
}
Und dann einfach MyCachedHttpClient
anstelle von HttpClient
überall verwenden.
Anmerkungen:
get()
-Funktion von HttpClient
verbirgt, da ich den Parameter options
hier nicht neu implementiert habe.Ich bin mir nicht sicher, was der Unterschied zwischen news.service.ts
und news-list.service.ts
ist, aber das Hauptkonzept besteht darin, dass Sie Bedenken voneinander trennen müssen. Die grundlegendste Trennung, die Sie tun können, ist die Trennung von "Datenanbietern" und "Datenkonsumenten".
Dies kann alles sein, was Daten abruft und verwaltet. Ob zwischengespeicherte Daten im Arbeitsspeicher, ein Serviceabruf usw. In Ihrem Beispiel scheint mir, dass news.service.ts
ein Web-API-Client/Proxy für alles ist, was mit Nachrichten zu tun hat.
Wenn dies eine kleine Datei ist, können Sie die gesamte Cache-Verwaltung für Nachrichten in diese Datei verschieben oder ... eine andere Komponente erstellen, die den Cache verwaltet und news.service.ts
umschließt. Diese Komponente würde Daten aus ihrem Cache bereitstellen. Wenn der Cache nicht vorhanden ist oder abgelaufen ist, werden news.service.ts
-Methoden aufgerufen. Auf diese Weise besteht die einzige Verantwortung von news.service.ts
darin, Ajax-Anforderungen an die API zu stellen.
Hier ein Beispiel ohne Versprechen, Observables oder Fehlerbehandlung, nur um Ihnen eine Vorstellung zu geben ...
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;
}
}
Dies wäre eine beliebige Komponente, die Daten benötigt, ein Nachrichtenticker auf der Startseite, eine Benachrichtigung über eine Badge irgendwo im Navigationsmenü. Möglicherweise gibt es Komponenten (oder Ansichten), die newsbezogene Daten benötigen. Aus diesem Grund sollten diese Komponenten/Ansichten nicht wissen müssen, woher die Daten stammen.
Diese Komponenten verwenden "Datenanbieter" als Hauptdatenquelle
Der Cache muss nur an einem einzigen Ort verwaltet werden (und kann auch verwaltet werden) sowie netzwerkbezogene Vorgänge