Angular中导入抽象类至HTTP拦截器报错:this.cache.get不是函数
看起来你遇到的问题核心是抽象类无法被Angular依赖注入直接实例化,你在模块里直接注册了HttpCache抽象类,但Angular没办法创建它的实例,导致注入到CachingInterceptor里的cache并不是一个有效的实现对象,调用get方法自然会抛出is not a function的错误。下面是具体的解决步骤:
第一步:创建HttpCache的具体实现类
抽象类只是定义了方法规范,你需要写一个实际的类来实现这些方法,比如基于内存的缓存实现:
import { Injectable } from '@angular/core'; import { HttpRequest, HttpResponse } from '@angular/common/http'; import { HttpCache } from './interface/http-cache.interface'; @Injectable() export class InMemoryHttpCache implements HttpCache { // 用Map存储缓存的响应,确保键的唯一性 private cacheStore = new Map<string, HttpResponse<any>>(); get(req: HttpRequest<any>): HttpResponse<any>|null { // 用请求的完整URL(含参数)作为缓存键 const cacheKey = req.urlWithParams; return this.cacheStore.get(cacheKey) || null; } put(req: HttpRequest<any>, resp: HttpResponse<any>): void { const cacheKey = req.urlWithParams; // 克隆响应避免原对象被后续操作修改 this.cacheStore.set(cacheKey, resp.clone({ body: resp.body })); } }
第二步:修改模块的Providers配置,绑定抽象类到具体实现
在你的NgModule里,不能直接把抽象类HttpCache放到providers数组里,需要通过provide和useClass告诉Angular:当需要注入HttpCache类型的依赖时,使用InMemoryHttpCache的实例。修改后的providers配置如下:
@NgModule({ declarations: [ RootComponent ], imports: [ BrowserModule, Ng2Webstorage, ApplicationRouterModule, HttpClientInMemoryWebApiModule.forRoot(InMemoryDataService) ], exports: [], providers: [ RootService, // 关键:绑定抽象类到具体实现类 { provide: HttpCache, useClass: InMemoryHttpCache }, { provide: HTTP_INTERCEPTORS, useClass: CachingInterceptor, multi: true } ] }) export class YourRootModule { }
第三步:验证拦截器的注入逻辑
现在Angular会自动把InMemoryHttpCache的实例注入到CachingInterceptor的cache参数里,你可以正常调用this.cache.get(req)了。如果需要扩展缓存逻辑(比如改用localStorage),只需要新建一个实现HttpCache的类,然后修改providers里的useClass即可,完全符合开闭原则。
补充:为什么之前的写法会报错?
抽象类的设计目的是作为基类,定义子类必须实现的方法,但它本身不能被实例化。你之前直接在providers里注册HttpCache,Angular尝试创建它的实例时会失败,导致注入的cache是一个无效的空对象,所以调用get方法时会提示is not a function。
内容的提问来源于stack exchange,提问作者Uland Nimblehoof

