摘要:返回的對(duì)象同時(shí)是類型的,擁有方法。由于調(diào)用后,開始執(zhí)行,因此,會(huì)返回一個(gè)供調(diào)用者來終止執(zhí)行。是的一個(gè)衍生類,具有最新的值的概念。舉一個(gè)形象的例子,表示一個(gè)人的生日,而則表示一個(gè)人的歲數(shù)。
什么是Subject? 在RxJS中,Subject是一類特殊的Observable,它可以向多個(gè)Observer多路推送數(shù)值。普通的Observable并不具備多路推送的能力(每一個(gè)Observer都有自己獨(dú)立的執(zhí)行環(huán)境),而Subject可以共享一個(gè)執(zhí)行環(huán)境。
Subject是一種可以多路推送的可觀察對(duì)象。與EventEmitter類似,Subject維護(hù)著自己的Observer。
每一個(gè)Subject都是一個(gè)Observable(可觀察對(duì)象) 對(duì)于一個(gè)Subject,你可以訂閱(subscribe)它,Observer會(huì)和往常一樣接收到數(shù)據(jù)。從Observer的視角看,它并不能區(qū)分自己的執(zhí)行環(huán)境是普通Observable的單路推送還是基于Subject的多路推送。
Subject的內(nèi)部實(shí)現(xiàn)中,并不會(huì)在被訂閱(subscribe)后創(chuàng)建新的執(zhí)行環(huán)境。它僅僅會(huì)把新的Observer注冊(cè)在由它本身維護(hù)的Observer列表中,這和其他語言、庫(kù)中的addListener機(jī)制類似。
每一個(gè)Subject也可以作為Observer(觀察者) Subject同樣也是一個(gè)由next(v),error(e),和 complete()這些方法組成的對(duì)象。調(diào)用next(theValue)方法后,Subject會(huì)向所有已經(jīng)在其上注冊(cè)的Observer多路推送theValue。
下面的例子中,我們?cè)赟ubject上注冊(cè)了兩個(gè)Observer,并且多路推送了一些數(shù)值:
var subject = new Rx.Subject(); subject.subscribe({ next: (v) => console.log("observerA: " + v) }); subject.subscribe({ next: (v) => console.log("observerB: " + v) }); subject.next(1); subject.next(2);
控制臺(tái)輸出結(jié)果如下:
observerA: 1 observerB: 1 observerA: 2 observerB: 2
既然Subject是一個(gè)Observer,你可以把它作為subscribe(訂閱)普通Observable時(shí)的參數(shù),如下面例子所示:
var subject = new Rx.Subject(); subject.subscribe({ next: (v) => console.log("observerA: " + v) }); subject.subscribe({ next: (v) => console.log("observerB: " + v) }); var observable = Rx.Observable.from([1, 2, 3]); observable.subscribe(subject); // 你可以傳遞Subject來訂閱observable
執(zhí)行后結(jié)果如下:
observerA: 1 observerB: 1 observerA: 2 observerB: 2 observerA: 3 observerB: 3
通過上面的實(shí)現(xiàn):我們發(fā)現(xiàn)可以通過Subject將普通的Observable單路推送轉(zhuǎn)換為多路推送。這說明了Subject的作用——作為單路Observable轉(zhuǎn)變?yōu)槎嗦稯bservable的橋梁。
還有幾種特殊的Subject 類型,分別是BehaviorSubject,ReplaySubject,和 AsyncSubject。
多路推送的Observable在以后的語境中,每當(dāng)提到“多路推送的Observable”,我們特指通過Subject構(gòu)建的Observable執(zhí)行環(huán)境。否則“普通的Observable”只是一個(gè)不會(huì)共享執(zhí)行環(huán)境并且被訂閱后才生效的一系列值。
通過使用Subject可以創(chuàng)建擁有相同執(zhí)行環(huán)境的多路的Observable。
下面展示了多路的運(yùn)作方式:Subject從普通的Observable訂閱了數(shù)據(jù),然后其他Observer又訂閱了這個(gè)Subject,示例如下:
var source = Rx.Observable.from([1, 2, 3]); var subject = new Rx.Subject(); var multicasted = source.multicast(subject); // 通過`subject.subscribe({...})`訂閱Subject的Observer: multicasted.subscribe({ next: (v) => console.log("observerA: " + v) }); multicasted.subscribe({ next: (v) => console.log("observerB: " + v) }); // 讓Subject從數(shù)據(jù)源訂閱開始生效: multicasted.connect();
multicast方法返回一個(gè)類似于Observable的可觀察對(duì)象,但是在其被訂閱后,它會(huì)表現(xiàn)Subject的特性。 multicast 返回的對(duì)象同時(shí)是ConnectableObservable類型的,擁有connect() 方法。
connect()方法非常的重要,它決定Observable何時(shí)開始執(zhí)行。由于調(diào)用connect()后,Observable開始執(zhí)行,因此,connect()會(huì)返回一個(gè)Subscription供調(diào)用者來終止執(zhí)行。
引用計(jì)數(shù)通過手動(dòng)調(diào)用connect()返回的Subscription控制執(zhí)行十分繁雜。通常,我們希望在有第一個(gè)Observer訂閱Subject后自動(dòng)connnect,當(dāng)所有Observer都取消訂閱后終止這個(gè)Subject。
我們來分析一下下面例子中subscription的過程:
第一個(gè)Observer 訂閱了多路推送的 Observable
多路Observable被連接
向第一個(gè)Observer發(fā)送 值為0的next通知
第二個(gè)Observer訂閱了多路推送的 Observable
向第一個(gè)Observer發(fā)送 值為1的next通知
向第二個(gè)Observer發(fā)送 值為1的next通知
第一個(gè)Observer取消了對(duì)多路推送的Observable的訂閱
向第二個(gè)Observer發(fā)送 值為2的next通知
第二個(gè)Observer取消了對(duì)多路推送的Observable的訂閱
取消對(duì)多路推送的Observable的連接
通過顯式地調(diào)用connect(),代碼如下:
var source = Rx.Observable.interval(500); var subject = new Rx.Subject(); var multicasted = source.multicast(subject); var subscription1, subscription2, subscriptionConnect; subscription1 = multicasted.subscribe({ next: (v) => console.log("observerA: " + v) }); subscriptionConnect = multicasted.connect(); setTimeout(() => { subscription2 = multicasted.subscribe({ next: (v) => console.log("observerB: " + v) }); }, 600); setTimeout(() => { subscription1.unsubscribe(); }, 1200); setTimeout(() => { subscription2.unsubscribe(); subscriptionConnect.unsubscribe(); }, 2000);
如果你不想顯式地調(diào)用connect()方法,可以在ConnectableObservable類型的Observable上調(diào)用refCount()方法。方法會(huì)進(jìn)行引用計(jì)數(shù):記錄Observable被訂閱的行為。當(dāng)訂閱數(shù)從 0 到 1時(shí)refCount() 會(huì)調(diào)用connect() 方法。到訂閱數(shù)從1 到 0,他會(huì)終止整個(gè)執(zhí)行過程。
refCount 使得多路推送的Observable在被訂閱后自動(dòng)執(zhí)行,在所有觀察者取消訂閱后,停止執(zhí)行。
下面是示例:
var source = Rx.Observable.interval(500); var subject = new Rx.Subject(); var refCounted = source.multicast(subject).refCount(); var subscription1, subscription2, subscriptionConnect; console.log("observerA subscribed"); subscription1 = refCounted.subscribe({ next: (v) => console.log("observerA: " + v) }); setTimeout(() => { console.log("observerB subscribed"); subscription2 = refCounted.subscribe({ next: (v) => console.log("observerB: " + v) }); }, 600); setTimeout(() => { console.log("observerA unsubscribed"); subscription1.unsubscribe(); }, 1200); setTimeout(() => { console.log("observerB unsubscribed"); subscription2.unsubscribe(); }, 2000);
執(zhí)行輸出結(jié)果如下:
observerA subscribed observerA: 0 observerB subscribed observerA: 1 observerB: 1 observerA unsubscribed observerB: 2 observerB unsubscribed
只有ConnectableObservables擁有refCount()方法,調(diào)用后會(huì)返回一個(gè)Observable而不是新的ConnectableObservable。
BehaviorSubjectBehaviorSubject是Subject的一個(gè)衍生類,具有“最新的值”的概念。它總是保存最近向數(shù)據(jù)消費(fèi)者發(fā)送的值,當(dāng)一個(gè)Observer訂閱后,它會(huì)即刻從BehaviorSubject收到“最新的值”。
BehaviorSubjects非常適于表示“隨時(shí)間推移的值”。舉一個(gè)形象的例子,Subject表示一個(gè)人的生日,而Behavior則表示一個(gè)人的歲數(shù)。(生日只是一天,一個(gè)人的歲數(shù)會(huì)保持到下一次生日之前。)
下面例子中,展示了如何用 0初始化BehaviorSubject,當(dāng)Observer訂閱它時(shí),0是第一個(gè)被推送的值。緊接著,在第二個(gè)Observer訂閱BehaviorSubject之前,它推送了2,雖然訂閱在推送2之后,但是第二個(gè)Observer仍然能接受到2:
var subject = new Rx.BehaviorSubject(0 /* 初始值 */); subject.subscribe({ next: (v) => console.log("observerA: " + v) }); subject.next(1); subject.next(2); subject.subscribe({ next: (v) => console.log("observerB: " + v) }); subject.next(3);
輸出結(jié)果如下:
observerA: 0 observerA: 1 observerA: 2 observerB: 2 observerA: 3 observerB: 3ReplaySubject
ReplaySubject 如同于BehaviorSubject是 Subject 的子類。通過 ReplaySubject可以向新的訂閱者推送舊數(shù)值,就像一個(gè)錄像機(jī)ReplaySubject可以記錄Observable的一部分狀態(tài)(過去時(shí)間內(nèi)推送的值)。
.一個(gè)ReplaySubject可以記錄Observable執(zhí)行過程中推送的多個(gè)值,并向新的訂閱者回放它們。
你可以指定回放值的數(shù)量:
var subject = new Rx.ReplaySubject(3 /* 回放數(shù)量 */); subject.subscribe({ next: (v) => console.log("observerA: " + v) }); subject.next(1); subject.next(2); subject.next(3); subject.next(4); subject.subscribe({ next: (v) => console.log("observerB: " + v) }); subject.next(5);
輸出如下:
observerA: 1 observerA: 2 observerA: 3 observerA: 4 observerB: 2 observerB: 3 observerB: 4 observerA: 5 observerB: 5
除了回放數(shù)量,你也可以以毫秒為單位去指定“窗口時(shí)間”,決定ReplaySubject記錄多久以前Observable推送的數(shù)值。下面的例子中,我們把回放數(shù)量設(shè)置為100,把窗口時(shí)間設(shè)置為500毫秒:
var subject = new Rx.ReplaySubject(100, 500 /* windowTime */); subject.subscribe({ next: (v) => console.log("observerA: " + v) }); var i = 1; setInterval(() => subject.next(i++), 200); setTimeout(() => { subject.subscribe({ next: (v) => console.log("observerB: " + v) }); }, 1000);
第二個(gè)Observer接受到3(600ms), 4(800ms) 和 5(1000ms),這些值均在訂閱之前的500毫秒內(nèi)推送(窗口長(zhǎng)度 1000ms - 600ms = 400ms < 500ms):
observerA: 1 observerA: 2 observerA: 3 observerA: 4 observerA: 5 observerB: 3 observerB: 4 observerB: 5 observerA: 6 observerB: 6 ...AsyncSubject
AsyncSubject是Subject的另外一個(gè)衍生類,Observable僅會(huì)在執(zhí)行完成后,推送執(zhí)行環(huán)境中的最后一個(gè)值。
var subject = new Rx.AsyncSubject(); subject.subscribe({ next: (v) => console.log("observerA: " + v) }); subject.next(1); subject.next(2); subject.next(3); subject.next(4); subject.subscribe({ next: (v) => console.log("observerB: " + v) }); subject.next(5); subject.complete();
輸出結(jié)果如下:
observerA: 5 observerB: 5
AsyncSubject 與 last() 操作符相似,等待完成通知后推送執(zhí)行過程的最后一個(gè)值。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/79377.html
摘要:項(xiàng)目簡(jiǎn)介本次使用了和開發(fā)了一個(gè)地址輸入框,主要實(shí)現(xiàn)的功能有限制輸入符合條件的字符并每隔兩位可以自動(dòng)添加用于分割的冒號(hào)。項(xiàng)目屏蔽了的事件處理,同時(shí)使用來手動(dòng)控制光標(biāo)。繼承于和因此同時(shí)具有和兩者的方法。后面的和都是需要利用最新的來進(jìn)行判斷的。 項(xiàng)目簡(jiǎn)介 本次使用了RxJS和react開發(fā)了一個(gè)mac地址輸入框,主要實(shí)現(xiàn)的功能有限制輸入符合條件的字符1-9,a-f,并每隔兩位可以自動(dòng)添加用于...
摘要:是的縮寫,起源于,是一個(gè)基于可觀測(cè)數(shù)據(jù)流結(jié)合觀察者模式和迭代器模式的一種異步編程的應(yīng)用庫(kù)。是基于觀察者模式和迭代器模式以函數(shù)式編程思維來實(shí)現(xiàn)的。學(xué)習(xí)之前我們需要先了解觀察者模式和迭代器模式,還要對(duì)流的概念有所認(rèn)識(shí)。 RxJS 是 Reactive Extensions for JavaScript 的縮寫,起源于 Reactive Extensions,是一個(gè)基于可觀測(cè)數(shù)據(jù)流 Stre...
摘要:仿宋可以把想像成一個(gè)可以發(fā)射事件的庫(kù)。在中用來處理異步事件的核心概念包括代表了未來可能會(huì)產(chǎn)生的一系列的值或事件的集合回調(diào)函數(shù)的集合,它知道如何去處理上產(chǎn)生的值或者事件,當(dāng)然也包括異常。 又一年要過去了,回顧2017,rxjs始終是我在項(xiàng)目里使用最頻繁的庫(kù),在我看來,它是一個(gè)非常優(yōu)秀的數(shù)據(jù)處理工具。年初的時(shí)候就計(jì)劃寫點(diǎn)什么,礙于目前公司的項(xiàng)目實(shí)在抽不出時(shí)間,這一拖就到了年底。臨近新年,總...
摘要:到底是什么先上代碼輸出這里可以把想象成一個(gè)函數(shù),這意味著你每次調(diào)用都會(huì)導(dǎo)致傳入里的回調(diào)函數(shù)重新執(zhí)行一次調(diào)用的方式為相當(dāng)于。接收函數(shù)返回值的方式也從改為通過傳入回調(diào)函數(shù)的方式獲取。具體看代碼運(yùn)行結(jié)果如上的第一個(gè)回調(diào)函數(shù)里的結(jié)構(gòu)是推薦的結(jié)構(gòu)。 通俗的方式理解Rx.js 序言 今早看民工叔的文章的時(shí)候, 發(fā)現(xiàn)對(duì)Rxjs所知甚少, 于是去官方看了下教程, 整理出一些東西, 寫成此文。Rxjs據(jù)...
摘要:技術(shù)積累經(jīng)過社區(qū)的努力學(xué)習(xí)資料還是很多的,官方中文文檔就已經(jīng)很不錯(cuò),不過我們先從天精通初步感受一下然后配合一些中文文檔來補(bǔ)充知識(shí)點(diǎn),最后再根據(jù)官方文檔來校驗(yàn)整個(gè)知識(shí)體系。資料學(xué)習(xí)操作符的時(shí)候可以對(duì)照彈珠圖的交互彈珠圖的中文版中文文檔 前言 最近準(zhǔn)備畢設(shè),技術(shù)選型的時(shí)候因?yàn)楣δ艿囊恍┬枨鬁?zhǔn)備將RxJs融入到項(xiàng)目中,考慮RxJs的時(shí)候因?yàn)橹暗募夹g(shù)棧還猶豫了一下,查了一些資料以及粗略瀏覽了...
閱讀 3200·2021-11-25 09:43
閱讀 3206·2021-11-23 09:51
閱讀 3518·2019-08-30 13:08
閱讀 1568·2019-08-29 12:48
閱讀 3594·2019-08-29 12:26
閱讀 396·2019-08-28 18:16
閱讀 2561·2019-08-26 13:45
閱讀 2428·2019-08-26 12:15