2017-08-03 21 views
5

HttpRequestHttpInterceptor kullanarak önbelleğe alma işlemlerini açısal 4.3'e göre gerçekleştirmeye çalışıyorum. Ama bir hata alıyorum.HttpInterceptor'ı açısal olarak kullanarak önbelleğe alma mümkün değil.

caching.interceptor.ts http isteği/yanıt için bir engelleyici olarak burada CachingInterceptor eser

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

: İşte benim kodudur. Ve modül oluşturduk benziyor ki: a

Token da [] modülünün sağlayıcıları sağlanan

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

app.module.ts. Bu belgelere göre açısal 4.3. Ama yine ben alıyorum hata gibi: Bir hizmeti gibi enjekte neden

  1. HttpCache sonra, soyut bir sınıftır:

    hata

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

    ben 2 soru var?

  2. Resmi belgelere göre uygulamam olmasına rağmen neden bu hatayı alıyorum? Ben Sorununuzu Söyleyebileceğim kadarıyla
+0

Çok istekte bulunan bir hatayı düzeltmek için cevabımı güncelledim, bir göz atın. –

+0

teşekkürler @WillShaver – Shree

cevap

10

Eğer son derece basit bir cache-all-in-şeyler uygulanması arıyorsanız: bu orijinal yönteminden güncellendiğini

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

Not. Orijinal intercept yönteminde bir hata oluştu - ilk döndürmeden önce aynı URL'nin birden çok isteği denendiyse, birden çok istek yine de sunucuya çarpacaktır.

Bu çözüm, sunucuya yalnızca bir isteğin iletilmesine izin verir.

Orijinal çözüm, posterity için aşağıdadır. (Önerilmez.)

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

Teşekkürler. Onun çok basit.:) – Shree

+0

@Shree İstediğiniz şey buysa, lütfen kabul edilen yanıt olarak işaretleyin. Değilse, eksik olanları açıklığa kavuşturun. –

2

bu

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

Bu sınıf uygulamak gerekir soyut sınıftır ve senin CachingInterceptor kullanmak bunun bir örneğini oluşturmak için yöntemler olmasıdır

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

sınıf

Sonra CachingInterceptor sınıfında HttpCacheService kullanın.

Ancak, bunları önbelleğe almaya çalışıyorsanız, nedenleri yalnızca bir dizi dizide saklamıyorsunuz? This article, yapmaya çalıştığınız şeyi nasıl gerçekleştireceğiniz konusunda iyi bir başlangıç ​​noktası olabilir.

+0

Benim durumumda çalıştığım çözüm için teşekkürler. :) –