iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 28
0
Modern Web

從零開始的Angular前端開發系列 第 28

# DAY 28 RxJS

之前我們用過 @Input()@Output(),完成父子元件間的資料傳遞,但若今天兩個 Component 不是父子關係,這個方法可能就行不通了,今天會簡單介紹 RxJS 以及如何解決我們前篇遇到的問題。

RxJS

RxJS 是一套非同步的函式庫,我們之前用的 HttpClient,在使用 post()get() 這些 function 時,實際上是回傳 Observable 的物件,這個類別就是 RxJS 提供的。

先簡單介紹一些名詞:

  • Observable 可觀察物件,也就是被觀察的對象
  • Observer 觀察者物件,會去觀察 Observable 物件。
  • subscribe() 訂閱動作,可以想像成在 ObserverObservable 中建立連結。
// http.service.ts

data$: Observable<any> = new Observable<any>();

login(data): Observable<any> {
    this.data$ = this.http.post('/api/user/login', data);
    return this.data$;
  }
// login.component.ts

onSubmit() {
    this.response$ = this.http.login(this.account);
    this.response$.subscribe(
      (result) => {
        console.log(result);
      }
    );
  }

這邊的 this.data$ 就是一個 Observable 物件,return 給 login.component.tsthis.response$

然後 this.response$.subscribe() 這邊是做訂閱的動作,subscribe() 裡面可以放一個 Observer 物件,或是放入三個 callback function。而 Observer 其實就是將 nexterrorcomplete 三個 function 包起來,所以其實沒甚麼差別。

 subscribe(observer?: PartialObserver<T>): Subscription;
 subscribe(next: null | undefined, error: null | undefined, complete: () => void):

我們用的是第二種,也就是直接傳一個 function,為第一個參數 next,error 跟 complete 另有用途,不過不傳也沒關係。next 可以理解為,當 Observable 的物件發生變化時,會通知ObserverObserver 會執行 next 裡面的事情。所以就會在收到資料後 用 console.log() 將資料印出。

next :
(result) => {
        console.log(result);
      }

所以我們現在知道一些事,在我們做訂閱這個動作後,Observable發生改變,就會讓 Observer 做一些事。

那如果我今天在 LoginComponent 裡呼叫了 this.http.login(),要怎麼讓 NavigationBarComponent 知道已經登入成功了呢?我們可以使用 Subject 物件。

Subject

我們在 HttpService 裡建立一個 Subject 物件,讓NavigationBarComponent 去訂閱它的變化。

接著,LoginComponent 呼叫 this.http.login(),拿到結果後,用 next 方法,把剛拿到的結果塞給 this.http.subNavigationBarComponent 就會偵測到變化,拿到剛剛 post() 的結果,改變 this.isLogin 的狀態。所以我們可以實現,在兩個非父子關係的元件用 Subject 傳遞訊息。

執行結果:


// http.service.ts
import { Observable, Subject } from 'rxjs';

  sub = new Subject<any>();
// navigation-bar.component.ts

this.http.sub.subscribe((res) => {
      this.isLogin = res.status;
      console.log('nav: ' + res.status);
    });
// login.component.ts

onSubmit() {
    this.response$ = this.http.login(this.account);
    this.response$.subscribe(
      (result) => {
        this.http.sub.next(result);
      }
    );
  }

上一篇
# DAY 27 部署 & 執行
下一篇
# DAY 29 圖表
系列文
從零開始的Angular前端開發30

尚未有邦友留言

立即登入留言