Так что в проекте, над которым я работаю, используется компонент angular datatables. Я выполняю некоторые настройки компонента (максимальный размер страницы и т. Д.) И загружаю данные из .NET Core WebAPI через компонент HttpClient. Большая часть данных довольно статична
Поскольку я не хочу каждый раз запрашивать у API какие-либо статические данные, я хочу кэшировать ответы от API и использовать их повторно, если время ожидания в кэше не истекло.
Я пробовал разные механизмы кэширования, но у всех одна и та же проблема. Я даже начал новый проект, который просто необходим, но та же проблема повторяется
Компонент, который показывает сетку:
<table datatable id="productGrid" [dtOptions]="dtOptions" [dtTrigger]="dtTrigger"
class="table table-striped table-hover">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let product of products">
<td>{{ product.productId }}</td>
<td>{{ product.nameCleaned }}</td>
</tr>
</tbody>
</table>
export class ProductComponent implements OnDestroy {
dtOptions: DataTables.Settings;
dtTrigger: Subject<any> = new Subject();
products: Product[] = [];
constructor(private http: HttpClient) {
this.dtOptions = {
pagingType: 'full_numbers',
pageLength: 10,
responsive: true,
dom: '<"dataTables_wrapper dt-bootstrap4"<"row"<"col-sm-12 col-md-6"<"dataTables_length"l>><"col-sm-12 col-md-6"<"dataTables_filter"f>>>rtp>'
};
//this.dtOptions.columnDefs.push({ "visible": false, "searchable": false, "targets": 0 });
this.http.get<Product[]>('https://localhost:44331/api/product/products').subscribe((products) => {
this.products = products;
this.dtTrigger.next();
});
}
ngOnDestroy(): void {
this.dtTrigger.unsubscribe();
}
}
Перехватчик
@Injectable()
export class CachingInterceptor implements HttpInterceptor {
constructor(private cache: CacheMapService) {}
intercept(req: HttpRequest<any>, next: HttpHandler) {
if (!this.isRequestCachable(req)) {
return next.handle(req);
}
const cachedResponse = this.cache.get(req);
if (cachedResponse !== null) {
return of(cachedResponse);
}
return next.handle(req).pipe(
tap(event => {
if (event instanceof HttpResponse) {
this.cache.put(req, event);
}
})
);
}
private isRequestCachable(req: HttpRequest<any>) {
return (req.method === 'GET') && (req.url.indexOf(CACHABLE_URL) > -1);
}
}
export const MAX_CACHE_AGE = 20000; // in milliseconds
@Injectable()
export class CacheMapService implements Cache {
cacheMap = new Map<string, CacheEntry>();
get(req: HttpRequest<any>): HttpResponse<any> | null {
const entry = this.cacheMap.get(req.urlWithParams);
if (!entry) {
return null;
}
const isExpired = (Date.now() - entry.entryTime) > MAX_CACHE_AGE;
return isExpired ? null : entry.response;
}
put(req: HttpRequest<any>, res: HttpResponse<any>): void {
const entry: CacheEntry = { url: req.urlWithParams, response: res, entryTime: Date.now() };
this.cacheMap.set(req.urlWithParams, entry);
this.deleteExpiredCache();
}
private deleteExpiredCache() {
this.cacheMap.forEach(entry => {
if ((Date.now() - entry.entryTime) > MAX_CACHE_AGE) {
this.cacheMap.delete(entry.url);
}
})
}
}
export interface CacheEntry {
url: string;
response: HttpResponse<any>
entryTime: number;
}
export abstract class Cache {
abstract get(req: HttpRequest<any>): HttpResponse<any> | null;
}
app.module.ts
export const httpInterceptorProviders = [
{ provide: HTTP_INTERCEPTORS, useClass: CachingInterceptor, multi: true }
];
const routes: Routes = [
{ path: 'products', component: ProductComponent },
{ path: '', component: AppComponent },
];
@NgModule({
declarations: [
AppComponent,
ProductComponent
],
imports: [
BrowserModule,
DataTablesModule,
HttpClientModule,
RouterModule.forRoot(routes)
],
providers: [httpInterceptorProviders,
CacheMapService,
{ provide: Cache, useClass: CacheMapService }],
bootstrap: [AppComponent]
})
export class AppModule { }
Проблема, с которой я столкнулся, заключается в том, что макет с данными не выполняется, когда данные поступают из кэша. Если данные извлекаются из API, все работает и сетка оформляется правильно, но когда результат получается из кеша, компоновка верна, все строки отображаются (без разбивки на страницы), окно поиска не отображается и т. Д. Это просто таблица без какого-либо форматирования.