RxJS在angular中的應用

前言

RxJS在看文檔後徹底是一片懵,直到我在angular的應用中遇到不少須要實現的功能的時候...RxJS完美!html

什麼是Observable?

Observable只是一個普通函數,要想讓他有所做爲,就須要跟observer一塊兒使用;前者是受後者是攻。而這個observer(後面咱們會介紹)只是一個帶有 next、error、complete 的簡單對象而已。最後,還須要經過 subscribe 訂閱來啓動Observable;不然它是不會有任何反應;能夠理解爲陌*爲了他們能在一塊兒而提供的環境,而訂閱也會返回一個可用於取消操做(在RxJS裏叫 unsubscribe)。node

當Observable設置觀察者後,而鏈接並獲取原始數據的這個過程叫生產者,多是DOM中的 click 事件、input 事件、或者更加複雜的HTTP通訊。app

爲了更好理解,先從一個簡單的示例開始:函數

import { Component } from '@angular/core';
import { Observable, Subscription } from 'rxjs';

@Component({
  selector: 'app-home',
  template: `<input type="text"> `
})
export class HomeComponent {
  ngOnInit() {
    const node = document.querySelector('input[type=text]');

    // 第二個參數 input 是事件名,對於input元素有一個 oninput 事件用於接受用戶輸入
    const input$ = Observable.fromEvent(node, 'input');
    input$.subscribe({
      next: (event: any) => console.log(`You just typed ${event.target.value}!`),
      error: (err) => console.log(`Oops... ${err}`),
      complete: () => console.log(`Complete!`)
    });
  }
}
複製代碼

示例中 Observable.fromEvent() 會返回一個Observable,而且監聽 input 事件,當事件被觸發後會發送一個 Event 給對應的observer觀察者。ui

什麼是Observer?

observer很是簡單,像上面示例中 subscribe 訂閱就是接收一個 observer 方法。this

通常在Angular咱們 subscribe 會這麼寫:spa

input$.subscribe((event: any) => {
});
複製代碼

從語法角度來說和 subscribe({ next, error, complete }) 是同樣的。code

當Observable產生一個新值時,會通知 observer 的 next(),而當捕獲失敗能夠調用 error()component

當Observable被訂閱後,除非調用observer的 complete()unsubscribe() 取消訂閱兩狀況之外;會一直將值傳遞給 observer。server

Observable的生產的值容許通過一序列格式化或操做,最終獲得一個有價值的數據給觀察者,而這一切是由一序列鏈式operator來完成的,每個operator都會產生一個新的Observable。而咱們也稱這一序列過程爲:流。

什麼是operator?

正如前面說到的,Observable能夠鏈式寫法,這意味着咱們能夠這樣:

Observable.fromEvent(node, 'input')
  .map((event: any) => event.target.value)
  .filter(value => value.length >= 2)
  .subscribe(value => { console.log(value); });
複製代碼

下面是整個順序步驟:

假設用戶輸入:a Observable對觸發 oninput 事件做出反應,將值以參數的形式傳遞給observer的 next()。 map() 根據 event.target.value 的內容返回一個新的 Observable,並調用 next() 傳遞給下一個observer。 filter() 若是值長度 >=2 的話,則返回一個新的 Observable,並調用 next() 傳遞給下一個observer。 最後,將結果傳遞給 subscribe 訂閱塊。 你只要記住每一次 operator 都會返回一個新的 Observable,無論 operator 有多少個,最終只有最後一個 Observable 會被訂閱。

不要忘記取消訂閱。

爲何須要取消訂閱

Observable 當有數據產生時纔會推送給訂閱者,因此它可能會無限次向訂閱者推送數據。正由於如此,在Angular裏面建立組件的時候務必要取消訂閱操做,以免內存泄漏,要知道在SPA世界裏懂得擦屁股是一件必須的事。

unsubscribe

前面示例講過,調用 subscribe() 後,會返回一個 Subscription 可用於取消操做 unsubscribe()。最合理的方式在 ngOnDestroy 調用它。

ngOnDestroy() {
    this.inputSubscription.unsubscribe();
}
複製代碼
takeUnit

一個很是優雅的取消訂閱方法

Observable.fromEvent(node, 'input')
  .takeUnit((event: any) => this.show)
  .subscribe(value => { console.log(value); });

ngOnDestory(): void {
    this.show = false;
}
複製代碼

Subject

若是說 Observable 與 observer 是攻受結合體的話,那麼 Subject 就是一我的即攻亦受。正由於如此,咱們在寫一個Service用於數據傳遞時,老是使用 new Subject。下面展現一個例子:

@Injectable()
export class MessageService {
    private subject = new Subject<any>();

    send(message: any) {
        this.subject.next(message);
    }

    get(): Observable<any> {
        return this.subject.asObservable();
    }
}
複製代碼

當F組件須要向M組件傳遞數據時,咱們能夠在F組件中使用 send()。

constructor(myService: MyService)
ngOnInit() {
    this.myService.send('message');
}
複製代碼

M組件接收數據:

constructor(myService: MyService)
ngOnInit() {
    this.myService.get.subscribe(data => {
        console.log(data); // message
    })
}
複製代碼

EventEmitter

在angular中EventEmitter至關因而Subject

// my-component.component.ts
@outPut() onChange = new EventEmitter<String>();

onClick() {
    this.onChange.emit('hello world');
}
複製代碼
<!-- parent-coponent.component.html -->
<my-component onChange="change($event)"></my-component>
複製代碼
// parent-coponent.component.ts
change(value) {
    console.log(value) // hello world
}
複製代碼

最後

RxJS有不少操做符,詳情見個人另外一篇文章《RxJS(1) 常見Operators》。

相關文章
相關標籤/搜索