2017-10-19 78 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的實現細節。儘管如此,我已經在我的一個項目中成功使用了一年多了。

相關問題