2017-08-03 1 views
5

HttpRequestキャッシュを実装するには、HttpInterceptorを角度4.3のドキュメントに従って使用しています。しかし、私はエラーが発生しています。ここに私のコードは次のとおりです。4.3のHttpInterceptorを使用してキャッシュできません

caching.interceptor.ts HTTPリクエスト/レスポンスのためのインターセプタとして

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); 
      } 
     }) 
    } 
} 

ここCachingInterceptor作品。そして私は、モジュールを作成したように見えた:

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 {} 

トークンは、[]モジュールのプロバイダで提供されます。これは、角度4.3の文書によるものです。しかし、それでもまだ、私は取得していますエラーのように:それはサービスのように注入されている理由

  1. HttpCacheが、その後、抽象クラスである:

    エラー

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

    私は2つの質問がありますか?

  2. 公式のドキュメントに従って実装していますが、なぜそのエラーが発生しますか?
+0

私はマルチリクエストバグを修正するために私の答えを更新しました。 –

+0

ありがとう@WillShaver – Shree

答えて

10

あなたは超簡単なキャッシュ・オール・物事の実装を探しているなら:これはオリジナルのメソッドから更新されたことを

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; 
} 

注意。元のinterceptメソッドにはバグがありました。最初に返される前に同じURLの複数のリクエストが試行された場合、複数のリクエストが引き続きサーバーにヒットします。

この解決策では、1つの要求のみがサーバーに渡されます。

元の解決策は後世のためのものです。 (推奨しません)

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

ありがとう。とても簡単です。:) – Shree

+0

@Shreeこれがあなたの望むものなら、それを受け入れられた答えとしてマークしてください。そうでない場合は、それが欠けているものを明確にしてください。 –

2

私はあなたの問題は、これはあなたがこのクラスを実装する必要があるだろうし、それはあなたのCachingInterceptorで使用することのインスタンスを作成するためのメソッドです

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

抽象クラスであるということです伝えることができるものから、クラス

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

次に、あなたのCachingInterceptorクラスでHttpCacheServiceを使用しています。

しかし、それらをキャッシュしようとしている場合は、何らかの配列でリクエストを格納するだけではどうですか? This articleは、あなたがしようとしていることを達成するための良い出発点かもしれません。

+0

それは私の場合に働いたソリューションありがとう。 :) –

関連する問題