2017-10-19 86 views
2

我有一个休息客户端对象,它在生产环境中指向一个宁静的服务器并与之通信。但在开发模式下,它将简单地使用浏览器的存储以便于使用。如何使用不同的@Injectable进行开发和生产

我认为正确的做法是有两个接口实现,一个用于生产,另一个用于开发。通过这种方式,应用程序的其余部分不需要知道生产/开发情况,并且可以进行相同的测试。我需要做的是找到一种方法为每个环境注入正确的实例。顺便说一句,我不希望在开发代码中包含开发版本!

有谁知道如何做到这一点?

[更新]

我采用了棱角分明的CLI所以我使用的WebPack揭开序幕我的项目(我想!)。我更喜欢不使用外部模拟服务器,因为我宁愿将测试/开发环境与外部依赖关系隔离。那样,我需要在我的前端项目上工作的就是它本身。此外,即使我的问题是关注休息客户端,但当然这个问题可以推广到任何其他单身注射剂。

我在问这个问题,因为在我使用的其他DI框架(即Spring)中这样做是框架的一部分。所以我期待在这里看到同样的情况。

在这一点上,我知道我可以利用environment.production来检查它是否处于生产模式。但首先,这是一个运行时变量,但我想我正在寻找一个编译时间(尽管我不确定)。此外,尽管我们有不同的,但下面的代码会导致一个编译错误:

if (environment.production) { 
    import { RestClientService } from './rest-client.service'; 
} 
else { 
    import { MockRestClientService as RestClientService } from './mock-rest-client.service'; 
} 

ERROR in ... Duplicate identifier 'RestClientService'. 
ERROR in ... An import declaration can only be used in a namespace or module. 
+0

你使用什么构建工具? (即webpack,汇总或一些这样的?)据我所知,TypeScript本身在这种情况下不能有帮助。您需要在构建过程中将“包含”路径替换为该文件。 –

+0

当然,你总是可以在运行时根据某种配置或某些方式创建它,但是在代码中会有两个这样的实现,并且应用程序本身会使用正确的。 –

+0

为什么不使用'MockBackend'并拦截Http调用(https://semaphoreci.com/community/tutorials/testing-services-in-angular-2),只是对你的用例感到好奇;) – cyberpirate92

回答

2

使用factory provider此:

export function restClientFactory(http: HttpClient): RestClientService { 
    if (environment.production) { 
    return new RestClientService(http); 
    } else { 
    return new MockRestClientService(); 
    } 
} 

@NgModule({ 
    providers: [ 
    { provide: RestClientService, useFactory: restClientFactory, deps: [ HttpClient ] }, 
    ], 
}) 
class AppModule {} 

有条件import语句的方法行不通,因为静态import语句只允许在文件的顶层。它们不能嵌套在if/else声明中。您可以使用动态import()来克服此问题,但这也会导致您的捆绑包中包含这两种实现。


不幸的是,没有像在Spring中那样对DI进行编译时配置的技术可能性。

运行时检查的主要问题是两个实现都将包含在您的生产包中。您可以依靠作为生产版本的一部分的tree-shaking来确保您的模拟客户端不包含在生产捆绑包中。

由于environment.production变量永远不会发生变化,因此您可以预期if/else的一个分支永远不可达,因此可以通过树状摇晃过程从分组中删除。问题在于,做树震的工具无法理解它,因为变量未声明为const,而是作为对象的属性声明。

如果添加export const production = trueenvironment.prod.tsexport const production = falseenvironment.ts,并在if/else语句中使用这个变量的一个分支应该是成功的树从生产束动摇。

请注意,此方法依赖于Angular CLI的实现细节。尽管如此,我已经在我的一个项目中成功使用了一年多了。

相关问题