我想基于运行时标志提供API接口的模拟或实际实现。这是我目前的做法:
providers:[{
provide: MyApi,
useFactory: () => {
return env.useSpoofData ? mockMyApi : MyApi
}
}]
我已将mockMyApi
定义为:
export const mockMyApi: MyApi = {
get(): Observable<MyResponse> {
const resp: MyResponse = {items};
return observableOf(resp);
},
};
这个模拟版本有效,但真正的版本,当以这种方式提供时,不起作用。 (如果我不完全覆盖这个提供者那么真正的版本是有效的)
我已经尝试了两种方法来解决“真实”实现的符号。
一:
provide: MyApi,
deps: [MyApi],
useFactory: (real: MyApi) => env.spoof ? mockMyApi : real;
失败。构建时的循环依赖。
二:
provide: MyApi,
deps: [Injector],
useFactory: (inj: Injector) => env.spoof ? mockMyApi : inj.get(MyApi);
失败。堆栈在运行时溢出。
从useFactory返回时,实例化或提供类的正确方法是什么?或者,是否有更简单的方法来提供者覆盖?
您提供工厂,因此您不能简单地将注入令牌作为工厂结果传递。 mockMyApi
是一个常数,而MyApi
是一个类。因此,您需要创建该类的对象。这就是工厂通常使用的。使用deps
传递依赖关系,例如HttpClient
:
providers:[{
provide: MyApi,
useFactory: (http: HttpClient) => {
return env.useSpoofData ? mockMyApi : new MyApi(/* args, e.g. http */)
},
deps: [HttpClient]
}]
我能找到的最佳解决方案是创建一个新的“包装”API。然后,将所有消费者更改为指向新的MyApiWrapped
。在您的新实施中:
provide: MyApiWrapped,
deps: [Injector],
useFactory: (inj: Injector) => env.spoof ? mockMyApi : inj.get(MyApi);
这样,您可以提供任一实现,而不会导致循环依赖。此外,在这里使用Injector意味着您允许Angular管理服务的缓存单例实例并使用正确的依赖关系进行备份。