Angular-第6課-服務的基本觀念

Vincent Zheng
新手工程師的程式教室
5 min readNov 22, 2018

在上一課,我們把heroes組件顯示詳情的工作,交付給hero-detail組件負責,這是在html畫面的模組化。而本課要進行的是「程式」的模組化,利用「服務」這個角色,讓程式碼也可以重複使用。

課程關鍵字:#服務 #注入

一、服務的定義

到目前為止,取得hero資料與展示在畫面上這兩件事,都是讓組件來處理。但更好的做法,應該是讓組件專門展示畫面。至於取得資料的工作,可以交派給本課要介紹的「服務(Service)」。

用Spring來比喻的話,組件就像是Controller,它只專注於接收請求與回傳資料。而存取資料庫和資料處理的過程,則是呼叫Service來達成。Controller只要等著拿Service處理完的資料即可。

那麼請在終端機切換到專案根目錄,執行指令,建立名為hero的服務:

ng generate service 服務名稱ng generate service hero

這個指令會在/src/app目錄產生hero.service.ts的檔案,內容是這樣的:

import { Injectable } from '@angular/core';@Injectable({
providedIn: 'root',
})
export class HeroService {
constructor() { }}

服務只有一個ts檔,它會從Angular核心函式庫匯入「@Injectable」標記,並標記在這個類別上,代表它是一個「可注入」的服務。在Spring也是如此,服務類別會被標記@Service,賦予Spring元件的角色。

二、可注入的服務

讓我們用生活情境來比喻服務。公司的會計部門就像是「服務」的程式檔,其他員工則是呼叫該服務的程式檔。會計被「注入」到員工的工作流程中,因此員工出完差才能進行報帳的動作。

再次用Spring來比喻,注入就很像是「Autowired」!在Controller類別中會注入Service,用來處理請求並產生要回應的資料。而這個Service類別也有可能注入其他Service,進行更複雜的資料處理,彷彿公司的不同部門在合作一般。

那麼讓我們將hero服務的內容準備好,再注入到heroes組件的程式檔中。請在hero.service.ts中加入一個名為「getHeroes」的方法,使它能回傳之前定義好的hero資料。類別與陣列一樣請自行匯入。

getHeroes(): Hero[] {
return HEROES;
}

接下來開啟heroes.component.ts,在它的建構子(constructor)加入HeroService型態的參數,名稱為heroService,就像Java的建構子那樣。並在前面冠上「private」字眼,代表這是本類別的私有成員。完成後會像這樣子:

constructor(private heroService: HeroService) { }

如此便完成注入。當heroes組件因為顯示而被建立時,Angular會自動將HeroService的實體物件傳遞進來,也就是注入。現在heroes.component.ts已經可以在需要的地方使用這個HeroService服務了。

三、在程式中使用服務

這一節就要開始使用注入進來的服務。由於資料的來源將會改變,因此請開啟heroes.component.ts,把先前從外部匯入hero陣列的部份清除。並將這個類別的成員,heroes陣列改為普通的宣告,無初始值。調整後會像這樣子:

剛注入服務,準備使用的類別

接著在類別新增一個方法,名稱為「getHeroes」。實作內容是呼叫HeroService的getHeroes方法,取得hero陣列,再賦值給本類別的heroes。

getHeroes(): void {
this.heroes = this.heroService.getHeroes();
}

最後請在Angular的生命週期方法「ngOnInit」方法呼叫它,這樣就能在組件被建立時,透過HeroService取得資料。就算往後取得的方式改變,例如讀取另一個檔案,組件也不需要修改。組件只要專注於展示畫面即可。完成後執行應用程式,結果看起來一如往常。

至於為什麼不在建構子(constructor)呼叫Service的方法呢?在目前的範例是其實是可以的,不影響結果。但建構子的功能應該要是將它的參數賦值給類別的資料成員,而非做其他有的沒的事情。

而且如果Service是從網路下載資料,將這個工作放在建構子中也就太奇怪了。因此我們把呼叫Service的過程留到「ngOnInit」方法,讓Angular的生命週期機制來調度進行。

本課heroes組件最後的html檔

--

--

Vincent Zheng
新手工程師的程式教室

我是Vincent,是個來自資管系的後端軟體工程師。當初因為學校作業,才踏出寫部落格的第一步。這裡提供程式教學文章,包含自學和工作上用到的經驗,希望能讓讀者學到東西。我的部落已搬家至 https://chikuwa-tech-study.blogspot.com/