[譯] 認識 rxjs 中的 Subject

臘八粥啊發表於2019-04-15

原文連結:Understanding rxjs Subjects
原文作者:Luuk Gruijs;發表於2018年4月17日
譯者:yk;如需轉載,請註明出處,謝謝合作!

RxJS 是真的好用,它可以幫助我們更好地編輯/訂閱資料流。雖然單用 Observable(可觀察物件)就可以做很多事情,但 RxJS 還是提供了多種用於操控資料流的類,Subject(主題)就是其中之一。

如果你還不知道 Observable 是什麼的話,建議先讀讀我的另一篇文章:Understanding, creating and subscribing to observables in Angular。如果你覺得你明白 Observable 是什麼意思,那行我們繼續!

[譯] 認識 rxjs 中的 Subject

攝影:Anvesh Uppunuthula,來自 Unsplash

Subject

Subject 就好比 Observable。你可以訂閱它,就像你平時訂閱 Observable 一樣。它也有類似 next()error() 以及 complete() 的方法,就像你平時傳給 Observable 建構函式的 observer(觀察者)一樣。

使用 Subject 主要是為了多播(multicast)。Observable 預設是單播(unicast)的,而單播就意味著:對於每個訂閱者,都只有一個獨立的 Observable execution 與之對應。證明如下:

import * as Rx from "rxjs";

const observable = Rx.Observable.create((observer) => {
  observer.next(Math.random());
});

// 訂閱者甲
observable.subscribe((data) => {
  console.log(data); // 0.24957144215097515 (隨機數)
});

// 訂閱者乙
observable.subscribe((data) => {
  console.log(data); // 0.004617340049055896 (隨機數)
});
複製程式碼

由於 Observable 在設計上就是單播的,所以如果你希望使多個訂閱者收到相同的資料,那麼用 Observable 可能會非常麻煩。而 Subject 可以幫助我們解決這個問題。正如先前所說,Subject 可以用來實現多播。多播的基本含義是:一個 Observable execution 可以在多個訂閱者之間共享。

譯者注:每當我們呼叫一次 Observable.subscribe() 時,一個新的 Observable execution 就會被啟動。詳見 Observable

Subject 也可比作事件發射器(EventEmitter),其中註冊了多個事件監聽器。 當我們訂閱 Subject 時,它並不會啟動一個新的 execution 來傳送資料。而是在現有觀察者列表中註冊一個新的觀察者,僅此而已。

如何在多播中使用 Subject

多播是 Subject 的特性,使用 Subject 即可實現多播,無需任何技巧。下面是一個簡單的示例:

import * as Rx from "rxjs";

const subject = new Rx.Subject();

// 訂閱者 1
subject.subscribe((data) => {
  console.log(data); // 0.24957144215097515 (隨機數)
});

// 訂閱者 2
subject.subscribe((data) => {
  console.log(data); // 0.24957144215097515 (隨機數)
});

subject.next(Math.random());
複製程式碼

奶思!我們使兩個訂閱者獲得了相同的資料。然而,這並非 Subject 的唯一用途。

相比 Observable 只能作為資料的生產者,Subject 即可以作為生產者,也可以作為消費者。通過把 Subject 作為消費者使用,你可以將一個單播 Observable 轉換為多播。示例如下:

import * as Rx from "rxjs";

const observable = Rx.Observable.create((observer) => {
  observer.next(Math.random());
});

const subject = new Rx.Subject();

// 訂閱者 1
subject.subscribe((data) => {
  console.log(data); // 0.24957144215097515 (隨機數)
});

// 訂閱者 2
subject.subscribe((data) => {
  console.log(data); // 0.24957144215097515 (隨機數)
});

observable.subscribe(subject);
複製程式碼

將我們的 subject 傳遞給 subscribe(),使其接收由 observable 傳來的值(消費資料)。隨後,subject 的所有訂閱者都會立即收到這個值。

結論

如果你希望 Observable 的多個訂閱者接收到相同的資料,那就用 Subject 來代替 Observable。由於其 Observable execution 可以在多個訂閱者之間共享,所以 Subject 將確保每個訂閱者接收到的資料是絕對相等的。另外,Subject 還有幾種變體,我將在下一篇文章中詳細描述它們之間的區別。

想在阿姆斯特丹找到一份工作嗎?

譯者注:後面都是一些無關緊要的招聘資訊,我就不翻譯了,除非你真的想去阿姆斯特丹。

相關文章