2017-08-03 3 views
5

Ich versuche zu implementieren HttpRequest Caching mit HttpInterceptor wie in der Dokumentation von eckigen 4.3. Aber ich bekomme einen Fehler. Hier ist mein Code:Nicht in der Lage zu cachen mit HttpInterceptor in eckigen 4.3

caching.interceptor.ts

import { HttpRequest, HttpResponse, HttpInterceptor, HttpHandler, HttpEvent } from '@angular/common/http'; 
import { Injectable } from '@angular/core'; 
import { Observable } from 'rxjs/Observable'; 

import 'rxjs/add/operator/do'; 
import 'rxjs/add/observable/of'; 

abstract class HttpCache { 
    abstract get(req: HttpRequest<any>): HttpResponse<any>|null; 
    abstract put(req: HttpRequest<any>, resp: HttpResponse<any>): void; 
} 

@Injectable() 
export class CachingInterceptor implements HttpInterceptor { 
    constructor(private cache: HttpCache) {} 

    intercept(req: HttpRequest<any>, next: HttpHandler) : Observable<HttpEvent<any>> { 
     if(req.method !== 'GET'){ 
      return next.handle(req); 
     } 

     const cachedResponse = this.cache.get(req); 

     if(cachedResponse){ 
      return Observable.of(cachedResponse); 
     } 

     return next.handle(req).do(event => { 
      if(event instanceof HttpResponse){ 
       this.cache.put(req, event); 
      } 
     }) 
    } 
} 

hier CachingInterceptor arbeitet als Abfangjäger für http-Request/Response. Und ich habe ein geschaffenes Modul, das wie folgt aussieht:

app.module.ts

import { NgModule } from '@angular/core'; 
import { BrowserModule } from '@angular/platform-browser'; 
import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http'; 

import { AppComponent } from './app.component/app.component'; 
import { HomePage } from './pages/home.page/home.page'; 
import { ProductsPage } from './pages/products.page/products.page'; 
import { AboutUsPage } from './pages/about-us.page/about-us.page'; 
import { UsersPage } from './pages/users.page/users.page'; 
import { DemoPage } from './pages/demo.page/demo.page'; 
import { appRouter } from './app.router/app.router'; 
import { CachingInterceptor } from './caching.interceptor/caching.interceptor'; 
import { AppService } from './app.service/app.service'; 

@NgModule({ 
    imports: [ BrowserModule, HttpClientModule, appRouter ], 
    declarations: [ AppComponent, HomePage, ProductsPage, DemoPage, AboutUsPage, UsersPage ], 
    providers: [ { 
     provide: HTTP_INTERCEPTORS, 
     useClass: CachingInterceptor, 
     multi: true 
    }, AppService ], 
    bootstrap: [ AppComponent ] 
}) 
export class AppModule {} 

Token auch in Anbieter zur Verfügung gestellt [] des Moduls. Dies ist gemäß der Dokumentation von eckigen 4.3. Aber immer noch ich bin immer Fehler wie:

Fehler

ERROR Error: Uncaught (in promise): Error: No provider for HttpCache! 
Error: No provider for HttpCache! 
    at injectionError (reflective_errors.ts:71) 

Ich habe 2 Fragen:

  1. HttpCache ist eine abstrakte Klasse, warum ist es dann wie ein Service injiziert?
  2. Obwohl ich es nach der offiziellen Dokumentation implementiere, warum bekomme ich dann diesen Fehler?
+0

Ich habe meine Antwort aktualisiert, um einen Fehler mit mehreren Anfragen zu beheben, überprüfen Sie es. –

+0

danke @WillShaver – Shree

Antwort

10

Wenn Sie suchen für eine super-einfache Cache-all-the-Dinge Umsetzung:

import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from "@angular/common/http"; 
import { Injectable } from "@angular/core"; 
import { Observable } from "rxjs/Observable"; 

@Injectable() 
export class CacheInterceptor implements HttpInterceptor { 
    private cache: { [name: string]: AsyncSubject<HttpEvent<any>> } = {}; 

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { 
    if (request.method !== "GET") { 
     return next.handle(request); 
    } 
    const cachedResponse = this.cache[request.urlWithParams] || null; 
    if (cachedResponse) { 
     return cachedResponse.delay(0); 
    } 
    const subject = this.cache[request.urlWithParams] = new AsyncSubject<HttpEvent<any>>(); 
    next.handle(request).do(event => { 
     if (event instanceof HttpResponse) { 
      subject.next(event); 
      subject.complete(); 
     } 
    }).subscribe(); // must subscribe to actually kick off request! 
    return subject; 
} 

Beachten Sie, dass diese von der ursprünglichen Methode aktualisiert wurde. Die ursprüngliche intercept Methode hatte einen Fehler - wenn mehrere Anfragen der identischen URL vor der ersten Rückgabe versucht wurden, würden mehrere Anfragen immer noch den Server treffen.

Mit dieser Lösung kann nur eine Anfrage an den Server weitergeleitet werden.

Die ursprüngliche Lösung ist unten für die Nachwelt. (Nicht empfohlen.)

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { 
    if (request.method !== "GET") { 
     return next.handle(request); 
    } 
    const cachedResponse = this.cache[request.urlWithParams] || null; 
    if (cachedResponse) { 
     return Observable.of(cachedResponse); 
    } 

    return next.handle(request).do(event => { 
     if (event instanceof HttpResponse) { 
      this.cache[request.urlWithParams] = event; 
     } 
    }); 
} 
+0

Danke. Es ist so einfach.:) – Shree

+0

@Shree, wenn dies das ist, was Sie wollten, bitte markieren Sie es als die angenommene Antwort. Wenn nicht, bitte klären Sie, was es fehlt. –

2

Von dem, was ich Ihrem Problem sagen kann, ist, dass dies eine abstrakte Klasse

abstract class HttpCache { 
    abstract get(req: HttpRequest<any>): HttpResponse<any>|null; 
    abstract put(req: HttpRequest<any>, resp: HttpResponse<any>): void; 
} 

Sie benötigen würden diese Klasse implementieren und es Methoden, um eine Instanz davon zu schaffen, in Ihrem CachingInterceptor verwenden

Klasse
export class HttpCacheService implements HttpCache { 
    get(req: HttpRequest<any>): HttpResponse<any>|null { 
     // Some logic 
    } 
    put(req: HttpRequest<any>, resp: HttpResponse<any>): void { 
     //Some logic 
    } 
} 

Dann HttpCacheService in Ihrer CachingInterceptor Klasse.

Aber warum nicht nur die Anfragen in einer Art Array speichern, wenn Sie versuchen, sie zwischenzuspeichern? This article kann ein guter Ausgangspunkt sein, um zu erreichen, was Sie versuchen zu tun.

+0

Danke für die Lösung, die es in meinem Fall funktioniert hat. :) –

Verwandte Themen