最近拿了Ionic v7來玩,在建立專案時發現Ionic已經將所有的組建都變成了standalone component,應該說整個專案就是standalone application,由於我還沒有完全體驗過standalone的強大,因此在玩Ionic v7時可以說是處處碰壁啊XD,其中一個就是今天的主題HttpInterceptor,這篇主記錄一下Angular14前和後HttpInterceptor的用法和轉變。



Angular 14前的HttpInterceptor用法

在Angular14之前用HttpInterceptor不外乎就是建立一個服務並且實作HttpInterceptor介面,然後寫一個方便註冊的Provider



最後在app.modules.tsprovider註冊我們定義好的HttpIntercepotrProvider

以上是Angular 14之前設定HttpInterceptor的方式。


Angular 14後的HttpInterceptor用法

當Angular 14發佈standalone component後,也可以將整個Application轉換成standalone application,而轉換後將不再有app.modules.ts,這時候就會遇到第一個困難就是providers要加在哪裡?天真的我以為standalone就直接在imports裡面使用就可以,但事情似乎沒有這麼簡單XD,這裡我拿IonicModule.forRoot()當作範例可以參考下圖的錯誤訊息

在一番爬文後才知道原來在main.ts裡面也做了不小的變化,如果是使用app.modules.ts的AppModule作為進入點就是使用如下圖的方式

但是由於standalone的關係就不再有AppModule,因此main.ts的進入函式就會換成bootstrapApplication,

可以看到第二個參數是帶入一個ApplicationConfig參數,而這裡就是新的設定provider的地方,是說我以前好像很少會關注main.ts這個檔案XD
💡ApplicationConfig提供了providers的屬性

接著我們把HttpInterceptorProvider加到bootstrapApplication的providers內,存檔後執行會發現console.log報錯:No provider for Httpclient !,該錯誤是因為沒有引入HttpClientModule


天真無邪的我又以為在AppComponent Import HttpClientModule就可以,不過人生不會是一帆風順的,問題依舊還在,後來一番研究才發現原來答案就在importProvidersFrom(其實上圖就有了XD),把HttpClientModule帶入importProvidersFrom後就可以正常運行了!



Angular 15後的HttpInterceptor用法

到了Angular 15後我們可以使用一個新的方法叫做:provideHttpClient,這個方法等同於importProvidersFrom(HttpClientModule)

改成provideHttpClient並且在使用時可能會發現HttpInterceptor並沒有正確被執行,這是因為改成provideHttpClient後需要添加參數才能啟用特定的功能,如:HttpInterceptor。由於HttpInterceptor是一個服務因此加入withInterceptorsFromDi(),它可以告訴應用程式你的HttpInterceptor是一個Di注入的服務

而Angular 15還提供了另外一個註冊HttpInterceptor的方法:withInterceptors([]),陣列參數可以帶入多個HttpInterceptorFn的方法

它的用法就跟Router Guard的概念一樣,捨棄了服務,改成Function。另外如果在Function內要使用其它Service也可以使用Angular 14加強後的inject方法取得我們要的Service,這樣也不用擔心改成Function後沒地方取得Service的問題!

最後把這個function加到withInterceptors的陣列參數中就可以運作啦!這樣的好處甚至不需要再加HttpInterceptorProvider是不是更方便呢!




總結

自從出了standalone後整個專案變得很多(少了很多Module),也因為換成了standalone,在使用HttpInterceptor時從一個服務變成一個function整體來說是簡化了不少,至於要用什麼方式就看個人的習慣而定沒有一定哦!但是真要選的話我更喜歡使用function簡潔有力的寫法,另外官方文檔也有提到withInterceptorsFromDi在未來的版本可能會淘汰
因此我還是推薦使用function寫法哦!