无法在angular 4.3中使用HttpInterceptor进行缓存 [英] Not able to cache using HttpInterceptor in angular 4.3

查看:88
本文介绍了无法在angular 4.3中使用HttpInterceptor进行缓存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用HttpInterceptor来实现HttpRequest缓存,具体方法请参见角度4.3的文档.但是我遇到了一个错误.这是我的代码:

I'm trying to implement HttpRequest caching using HttpInterceptor as per the documentation by angular 4.3. But I'm getting an error. Here is my code:

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

此处CachingInterceptor用作HTTP请求/响应的拦截器.我创建了一个看起来像这样的模块:

Here CachingInterceptor works as an interceptor for http request/response. And I've created module a which looks like:

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

令牌也提供在模块的provider []中.这是根据角度4.3的文档进行的.但是仍然出现类似以下错误:

Token is also provided in providers[] of module. This is as per the documentation by angular 4.3. But still i'm getting error like:

错误

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

我有2个问题:

  1. HttpCache是一个抽象类,那么为什么它像服务一样被注入?
  2. 即使我按照官方文档实施了该程序,但为什么会出现该错误?
  1. HttpCache is an abstract class, then why is it injected like a service?
  2. Even though I'm implementing it as per the official documentation, then why am I getting that error?

推荐答案

如果您正在寻找一种超简单的一切皆有之物"实现:

If you're looking for a super-simple cache-all-the-things implementation:

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的请求,则多个请求仍会到达服务器.

Note that this has been updated from the original method. The original intercept method had a bug - if multiple requests of the identical url were attempted prior to the first returning, multiple requests would still hit the server.

此解决方案仅允许将一个请求传递到服务器.

This solution allows only one request to be passed through to the server.

以下是后代的原始解决方案. (不推荐.)

The original solution is below for posterity. (Not recommended.)

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

这篇关于无法在angular 4.3中使用HttpInterceptor进行缓存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆