# Day24 【牙起來】 訂閱Subscribe、被訂閱者Observable - RxJS > `Observable`中文直譯為**可觀測物件** > 我比較喜歡稱他為 **被訂閱者**,簡單又直觀 --- ## 訂閱與被訂閱 訂閱的世界裡有**三個名詞** * `Subscriber` 訂閱者: 可以訂閱別人 * `Observable` 被訂閱者: 可以被訂閱 * `Subscribe` 訂閱: 動詞,訂閱本身的行為 每當**被訂閱者**完成一部影片,會發出通知, 告訴所有**訂閱**他的**訂閱者**,說:「欸欸我出一個新的影片囉,快叫大家來看!」 > Subscriber 訂閱者 -> (Subscribe) -> Observable 被訂閱者 > > 中文為: 『訂閱者 訂閱了 被訂閱者』 > 這整個過程則稱為 **訂閱事件** --- ## 程式裡的被訂閱者 ### 方法一、直接訂閱的形式 依照上一次的範例來看,在`store.component.ts`中 ```typescript= constructor(private http: HttpClient) { let url = 'https://63403667d1fcddf69cb402b7.mockapi.io/api/v1/weapons'; this.http.get(url).subscribe(result => { console.log(result); }); } ``` * 藍框內 `this.http.get(url)` 代表**被訂閱者** * 橘框 `.subscribe()` 表示**訂閱的動作**  `subscribe()` 的裡面則是一個`callBack`函式,把回來的資料`result`給印出來 ### 方法二、給個變數直接訂閱 也可以寫成這樣,讓變數`getData$`成為`Observable` 最後再`subscribe()`他 ```typescript= export class StoreComponent { constructor(private http: HttpClient) { let url = 'https://63403667d1fcddf69cb402b7.mockapi.io/api/v1/weapons'; let getData$ = this.http.get(url); getData$.subscribe( result => { console.log(result); } ) } } ``` > 在變數命名慣例上,會對`Observable`物件尾端加上錢字號 `$` > > 後綴`$`能讓人們意會到這個物件是**資料流**,而非資料本身 ### 方法三、統一管理的形式 也可以長成這樣子 使用`Subscription`物件來集中管理所有的 **訂閱事件** ```typescript= export class StoreComponent { subscription = new Subscription(); constructor(private http: HttpClient) { let url = 'https://63403667d1fcddf69cb402b7.mockapi.io/api/v1/weapons'; let getData$ = this.http.get(url); this.subscription.add( getData$.subscribe( result => { console.log(result); } ) ) } } ``` 但這個樣子形式還是有點醜,似乎跟原本一樣,沒有什麼意義 所以我們可以再加上 `RxJS` 的 `.pipe()` 方法,把要處理的事情都丟進去 `.tap()` 就是在`pipe()`管線中要他執行某些事情 **Do Something** 的意思 把要做的事情、醜醜的code都包裝起來,對外僅露出短短的一行`getData$.subscribe()` ```typescript= export class StoreComponent { subscription = new Subscription(); constructor(private http: HttpClient) { let url = 'https://63403667d1fcddf69cb402b7.mockapi.io/api/v1/weapons'; let getData$ = this.http.get(url).pipe( tap( result => { console.log(result); } ) ); this.subscription.add(getData$.subscribe()); } } ``` 或者這樣, 先將資料流`subscribe()`,再放進`Subscription`物件中 ```typescript= export class StoreComponent { subscription = new Subscription(); constructor(private http: HttpClient) { let url = 'https://63403667d1fcddf69cb402b7.mockapi.io/api/v1/weapons'; let getData$ = this.http.get(url).pipe( tap( result => { console.log(result); } ) ).subscribe(); this.subscription.add(getData$); } } ``` 為什麼推薦這樣子寫呢? 因為等專案大一點之後,如果用**方法一** 可能會看到類似如下的程式碼 #### 不小心就做了多次訂閱 ```typescript= constructor(private http: HttpClient) { let url = 'https://63403667d1fcddf69cb402b7.mockapi.io/api/v1/weapons'; let getData$ = this.http.get(url); this.subscription.add( getData$.subscribe( result => { console.log(result); } ) ) ... this.subscription.add( getData$.subscribe( result => { console.log(result); } ) ) } ``` 運行結果  而使用`Subscription`物件 #### 對同一個資料流新增多次訂閱事件,也只會做一次訂閱 ```typescript= this.subscription.add(getData$); this.subscription.add(getData$); this.subscription.add(getData$); ``` 運行結果  把訂閱集中、收集起來,不僅能確保**只做了一次訂閱** 對於後續接手的人來說,也能很明確知道這個元件的程式內 總共對哪些資料流做了訂閱,可以一目瞭然 ```typescript= this.subscription.add(getData1$); this.subscription.add(getData2$); this.subscription.add(getData3$); ```
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up