原文連接:Understanding rxjs BehaviorSubject, ReplaySubject and AsyncSubject
原文做者:Luuk Gruijs;發表於2018年5月4日
譯者:yk;如需轉載,請註明出處,謝謝合做!javascript
Subject 的做用是實現 Observable 的多播。因爲其 Observable execution 是在多個訂閱者之間共享的,因此它能夠確保每一個訂閱者接收到的數據絕對相等。不只使用 Subject 能夠實現多播,RxJS 還提供了一些 Subject 的變體以應對不一樣場景,那就是:BehaviorSubject、ReplaySubject 以及 AsyncSubject。java
若是你還不知道 Subject(主題)是什麼的話,建議先讀讀個人上一篇文章:認識 rxjs 中的 Subject。若是你以爲 OK 沒問題,那咱繼續!git
攝影:Cory Schadt,來自 Unsplashgithub
BehaviorSubject 是 Subject 的變體之一。BehaviorSubject 的特性就是它會存儲「當前」的值。這意味着你始終能夠直接拿到 BehaviorSubject 最後一次發出的值。api
有兩種方法能夠拿到 BehaviorSubject 「當前」的值:訪問其 .value
屬性或者直接訂閱。若是你選擇了訂閱,那麼 BehaviorSubject 將直接給訂閱者發送當前存儲的值,不管這個值有多麼「久遠」。請看下面的例子:app
import * as Rx from "rxjs";
const subject = new Rx.BehaviorSubject(Math.random());
// 訂閱者 A
subject.subscribe((data) => {
console.log('Subscriber A:', data);
});
subject.next(Math.random());
// 訂閱者 B
subject.subscribe((data) => {
console.log('Subscriber B:', data);
});
subject.next(Math.random());
console.log(subject.value)
// 輸出
// Subscriber A: 0.24957144215097515
// Subscriber A: 0.8751123892486292
// Subscriber B: 0.8751123892486292
// Subscriber A: 0.1901322109907977
// Subscriber B: 0.1901322109907977
// 0.1901322109907977
複製代碼
詳細講解一下:dom
.value
屬性的形式獲取了 subject 當前的值並打印。這在同步的場景下很是好用,由於你沒必要訂閱 Subject 就能夠獲取它的值。另外,你可能發現了 BehaviorSubject 在建立時是須要設置一個初始值的。這一點在 Observable 上就很是難實現,而在 BehaviorSubject 上,只要傳遞一個值就好了。async
譯者注:當前版本的 RxJS 中
BehaviorSubject()
是必需要設置初始值的,不然會致使執行錯誤,而原文並無體現這一點。因此我在這一段作了較多改動,以避免誤導讀者。詳見 BehaviorSubject。post
相比 BehaviorSubject 而言,ReplaySubject 是能夠給新訂閱者發送「舊」數據的。另外,ReplaySubject 還有一個額外的特性就是它能夠記錄一部分的 observable execution,從而存儲一些舊的數據用來「重播」給新來的訂閱者。ui
當建立 ReplaySubject 時,你能夠指定存儲的數據量以及數據的過時時間。也就是說,你能夠實現:給新來的訂閱者「重播」訂閱前一秒內的最後五個已廣播的值。示例代碼以下:
import * as Rx from "rxjs";
const subject = new Rx.ReplaySubject(2);
// 訂閱者 A
subject.subscribe((data) => {
console.log('Subscriber A:', data);
});
subject.next(Math.random())
subject.next(Math.random())
subject.next(Math.random())
// 訂閱者 B
subject.subscribe((data) => {
console.log('Subscriber B:', data);
});
subject.next(Math.random());
// Subscriber A: 0.3541746356538569
// Subscriber A: 0.12137498878080955
// Subscriber A: 0.531935186034298
// Subscriber B: 0.12137498878080955
// Subscriber B: 0.531935186034298
// Subscriber A: 0.6664809293975393
// Subscriber B: 0.6664809293975393
複製代碼
簡單解讀一下代碼:
以前提到了你還能夠設置 ReplaySubject 的數據過時時間。讓咱們來看看下面這個例子:
import * as Rx from "rxjs";
const subject = new Rx.ReplaySubject(2, 100);
// 訂閱者A
subject.subscribe((data) => {
console.log('Subscriber A:', data);
});
setInterval(() => subject.next(Math.random()), 200);
// 訂閱者B
setTimeout(() => {
subject.subscribe((data) => {
console.log('Subscriber B:', data);
});
}, 1000)
// Subscriber A: 0.44524184251927656
// Subscriber A: 0.5802631630066313
// Subscriber A: 0.9792165506699135
// Subscriber A: 0.3239616040117268
// Subscriber A: 0.6845077617520203
// Subscriber B: 0.6845077617520203
// Subscriber A: 0.41269171141525707
// Subscriber B: 0.41269171141525707
// Subscriber A: 0.8211466186035139
// Subscriber B: 0.8211466186035139
複製代碼
一樣解讀一下代碼:
BehaviorSubject 和 ReplaySubject 均可以用來存儲一些數據,而 AsyncSubject 就不同了。AsyncSubject 只會在 Observable execution 完成後,將其最終值發給訂閱者。請看代碼:
import * as Rx from "rxjs";
const subject = new Rx.AsyncSubject();
// 訂閱者A
subject.subscribe((data) => {
console.log('Subscriber A:', data);
});
subject.next(Math.random())
subject.next(Math.random())
subject.next(Math.random())
// 訂閱者B
subject.subscribe((data) => {
console.log('Subscriber B:', data);
});
subject.next(Math.random());
subject.complete();
// Subscriber A: 0.4447275989704571
// Subscriber B: 0.4447275989704571
複製代碼
雖然這段代碼的輸出並很少,但咱們仍是照例解讀一下:
BehaviorSubject、ReplaySubject 和 AsyncSubject 均可以像 Subject 同樣被用於多播。它們各自都有一些額外的特性以適用於不一樣場景。
譯者注:這個結論好敷衍。。。