[Angular2官方tutorial學習03]service,Observable data,Rxjs,asynchronous service,service in service
官方的介紹有點文言文,但是對我來說,其實就是他把資料存取的部分獨立到另外一個資料夾(類似像是MVC的Model資料夾),讓整個程式碼的架構乾淨清潔,以下就開始介紹囉
@執行Angular CLI指令以新增一個服務, 服務名稱叫做hero
ng g s hero
然後打開檔案src\app\hero.service.ts,以下是預設的內容
內容中真正重要的部分就只有@Injectable注入的root關鍵字,是用來設定這個服務的可使用範圍,而root的意思當然是整個應用程式範圍都可以使用
實務上如果要縮小該服務的使用範圍,再google一下Injectable的設定相關資訊即可,沒必要現在全記
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class HeroService {
constructor() { }
}
同樣一個檔案繼續編輯,並且在HeroService的constructor下面加入下列程式碼
getHeroes(): Hero[] {
return HEROES;
}
加入完畢之後長這樣子
@接著回到src/app/heroes/heroes.component.ts,把該import的加進去
import { HeroService } from '../hero.service';
而且原本的heros直接吃假資料heroes = HEROES;
把他改成下面這樣,純粹宣告就好
heroes: Hero[];
然後把HeroesComponent的constructor改成下面這樣,準備要Inject the HeroService注入服務
constructor(private heroService: HeroService) { }
再來於HeroesComponent的constructor的下面再加入一個method,來呼叫這個service
getHeroes(): void {
this.heroes = this.heroService.getHeroes();
}
然後還是在src\app\heroes\heroes.component.ts,請在ngOnInit(){}裡面呼叫服務以取得資料,如下
官網有稍微提醒ngOnInit()才是用來取得資料用的,constructor則是用來設定基本的class的設定檔喔,別放錯地方了!
ngOnInit() {
this.getHeroes();
}
最後src\app\heroes\heroes.component.ts就會長的像是這樣
此時再次打開瀏覽器,你會發現跟之前完全沒兩樣,哈哈
不過的確把資料的存取獨立到Service去,架構上會比較好拉
@接著要把取得資料的動作改成非同步的:在上面呼叫Service且取得資料的方式並不是Ajax,因此需將他改寫成非同步的,想當然實務上可能在查詢資料的時候,畫面可能會有delay,下面步驟將會示範非同步的作法
@首先打開src/app/hero.service.ts,加入下列的import來使用Rxjs的函式庫以呼叫相關的非同步method
import { Observable, of } from 'rxjs';
然後把裡面原本的getHeros()這個method取代成如下。Observable就是Rxjs的關鍵字,他讓整個method變成非同步的
getHeroes(): Observable<Hero[]> {
return of(HEROES);
}
然後再打開src\app\heroes\heroes.component.ts,把裡面原本宣告的getHeros(): void....改成如下
sbuscribe就是Rxjs的關鍵字,他讓整個呼叫的過程變成非同步
getHeroes(): void {
this.heroService.getHeroes()
.subscribe(heroes => this.heroes = heroes);
}
最後src\app\heroes\heroes.component.ts程式碼長這樣
最後src\app\hero.service.ts程式碼長這樣
再次打開瀏覽器發現沒什麼不一樣 XD
其實取得hero list的時候,已經改用非同步的了拉~
@接著再來練習稍微不同的service的運用,首先再次執行下列angular cli指令以新增另一個component
ng g c messages
產生component完畢之後,打開/src/app/app.component.html,請將原本的下列內容
<h1>{{title}}</h1>
<app-heroes></app-heroes>
修改成下面這樣,用來測試新產生的component
<h1>{{title}}</h1>
<app-heroes></app-heroes>
<app-messages></app-messages>
目前的進度下,打開瀏覽器會看到message component會位於畫面的最下方
然後再執行下列angular cli指令,新增另一個message service
ng g s message
打開/src/app/message.service.ts,將整個內容修改如下
add()是把資料push到變數陣列中(即把資料push到cache裡面),而clear()就是清空變數陣列(即清空cache)
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class MessageService {
messages: string[] = [];
add(message: string) {
this.messages.push(message);
}
clear() {
this.messages = [];
}
}
接著打開/src/app/hero.service.ts,加入下列import,我們打算在hero service裡面呼叫message service
import { MessageService } from './message.service';
在同一個檔案,把constructor改成如下,表示要message service及將要在hero service裡面呼叫
constructor(private messageService: MessageService) { }
同一個檔案裡面,再去修改getHeroes()這個method,return的部分不變,但是額外多了this.messageService.add('HeroService: fetched heroes');
把一段訊息加入到message service的cache裡面了
getHeroes(): Observable<Hero[]> {
// TODO: send the message _after_ fetching the heroes
this.messageService.add('HeroService: fetched heroes');
return of(HEROES);
}
再來打開src/app/messages/messages.component.html,修改整個內容如下,這是用來顯示所有在message service裡面的變數陣列
<div *ngIf="messageService.messages.length">
<h2>Messages</h2>
<button class="clear"
(click)="messageService.clear()">clear</button>
<div *ngFor='let message of messageService.messages'> {{message}} </div>
</div>
最後這個步驟最重要,請打開/src/app/messages/messages.component.ts,並加入下列import以及修改constructor
因為剛才我們在src/app/messages/messages.component.html裡面,直接使用message service,因此必須在下面的constructor裡面宣告message service為public
import { MessageService } from '../message.service';
constructor(public messageService: MessageService) {}
我們回頭打開src\app\heroes\heroes.component.html來比較一下,這邊他只有使用變數,並非直接使用hero service
也因此在src\app\heroes\heroes.component.ts裡面的constructor無須宣告hero service為public
大概是這樣……下面是瀏覽器目前的畫面,雖然不重要 XD
但是還是貼一下截圖吧
目前為止的進度的整個專案檔提供給大家下載囉,放在dropbox
https://www.dropbox.com/s/1em2z6czkhsxiah/angular-tour-of-heros%20-%20%E5%AE%8C%E6%88%90service.rar?dl=0
參考資料:
[Angular2官方tutorial學習02]display list,master detail,click event,master detail advanced,幫css設定加上if
https://dotblogs.com.tw/kevinya/2018/10/26/105353
Services - Angular official tutorial
https://angular.io/tutorial/toh-pt4