日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【Rxjs】 - 解析四种主题Subject

發布時間:2023/12/18 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Rxjs】 - 解析四种主题Subject 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  原文地址:?https://segmentfault.com/a/1190000012669794

? ? ? ?

引言

  開發ngx(angular 2+)應用時,基本上到處都會用到rxjs來處理異步請求,事件調用等等。所以經常會使用Subject來處理源源不斷的數據流,比如input text change, toast notification等等。
  這都要依賴于Subject本身既可以是Observable也可以是Observer,也就是說subject既可以作為一個數據源,也可以本身成為一組訂閱者的代理。
  但當處理更加復雜的業務需求時,僅僅用Subject可能無法滿足要求,這個時候就考慮一下rxjs提供的其他Subject Class了, 例如BehaviorSubject?ReplaySubject?AsyncSubject, 接下來我們就來看一下他們跟Subject有什么區別,各自有什么特點,在什么時候更適合使用。

  [文中代碼均使用typescript]

Subject

  首先我們來創建一個Rxjs Subject, 數據的類型是number

let?subject1: Subject<number> =?new?Subject<number>();?// (A)

  然后我們使用Subject的next方法來emit(發射)1條數據

subject1.next(100); (B)

  接下來對subject1創建兩個訂閱,在subscription中直接打印接受到的數據

subject1.subscribe((res: number) => console.info("subjectA ", res)); // (C) subject1.subscribe((res: number) => console.info("subjectB ", res));

  接下來我在發射兩條數據

subject1.next(200); (D)subject1.next(300);

  好了,接下來我們就來看看console里面會打印出什么結果。
  也許有的同學會覺得結果是這樣的,因為Subject可以接收源源不斷的數據嘛,所以無論發射多少次數據,訂閱者都能接收到。

//output subjectA 100 subjectB 100 subjectA 200 subjectB 200 subjectA 300 subjectB 300

  這個結果不太對
  因為Subject的訂閱者只有在訂閱后,才能接收到數據源發射過來的值。
  所以在代碼塊C中, 訂閱者在訂閱數據源subject1之前, 無論代碼塊B執行多少次, 訂閱者也只能收到代碼C之后發射的數據。

  正確的結果應該是:

//output subjectA 200 subjectB 200 subjectA 300 subjectB 300

  這種情況在項目里經常能遇到,有時候我明明從數據源發射一個數據,但在訂閱者拿到的值卻是undefined或者null, 這就是因為訂閱者是在數據源發射之后創建的,自然無法接收到數據了。
  假如我們想在訂閱者創建之后,無論什么時候都能拿到數據, 這應該怎么辦呢? 那就要考慮使用BehaviourSubject了。

BehaviorSubject

  我們依舊使用剛才的例子, 創建一個BehaviorSubject, 默認值設為0.?BehaviorSubject需要給個默認值
  然后發射一條數據100,創建一個訂閱者,再發射一條數據200,再創建一個訂閱者,最后發射一條數據300。
  代碼如下:

let subject2: BehaviorSubject<number> = new BehaviorSubject<number>(0); subject2.next(100); subject2.subscribe((res: number) => console.info("behavior-subjectA ", res)); subject2.next(200); subject2.subscribe((res: number) => console.info("behavior-subjectB ", res)); subject2.next(300);

  這個時候結果就應該是:

//output behavior-subjectA 100 behavior-subjectA 200 behavior-subjectB 200 behavior-subjectA 300 behavior-subjectB 300

  由于BehaviorSubject是可以存儲最后一條數據或者初始默認值的, 所以無論訂閱者什么時候訂閱到數據源subject2上, 都能接收到數據。
  所以針對訂閱者behavior-subjectA, 他訂閱的時候,數據流里最后一條數據是100, 他能立即接收到。 然后依次能接收到最新的數據200和300。
  針對訂閱者behavior-subjectB, 他訂閱的時候,數據流里最后一條數據是200, 他能立即接收到。 然后只能能接收到最新的數據300了。

  BehaviorSubject給予我們的便利就是,無論何時訂閱到數據源,始終都能拿到最新的或者初始的數據,但也只能拿到一條數據,但當我們處理input text change事件時,需要拿到用戶輸入的所有字符,也就是數據流的所有數據,BehaviorSubject就無能為力了,這個時候我們考慮使用ReplaySubject了。

ReplaySubject

  我們依舊使用剛才的例子, 創建一個ReplaySubject, 發射兩條數據100和200,創建一個訂閱者,再發射一條數據300,再創建一個訂閱者,最后發射一條數據400。
  代碼如下:

let subject3: ReplaySubject<number> = new ReplaySubject<number>(); subject3.next(100); subject3.next(200); subject3.subscribe((res: number) => console.info("replay-subjectA ", res)); subject3.next(300); subject3.subscribe((res: number) => console.info("replay-subjectB ", res)); subject3.next(400);

  控制打印的結果將是:

//output replay-subjectA 100 replay-subjectA 200 replay-subjectA 300 replay-subjectB 100 replay-subjectB 200 replay-subjectB 300 replay-subjectA 400 replay-subjectB 400

  ReplaySubject會存儲數據流中的所有數據,無論何時訂閱到subject3,訂閱者都能獲取了訂閱之前數據流里的所有數據,然后依舊獲取到接下來獲取的到的新數據。
  就像ReplaySubject類名的中Replay, 一旦訂閱到數據源,就會將數據流像放電影一樣重新放一遍給你。

  訂閱者replay-subjectA訂閱到subject3的時候,數據流里已經有了100和200, 接收并打印出來。
  最后打印新數據300和400.
  訂閱者replay-subjectB訂閱到subject3的時候,數據流里已經有了100,200,300, 接收并打印出來。最后打印新數據400.

  接下來就要說下最后一種Subject了,也就是AsyncSubject

AsyncSubject

  AsyncSubject和BehaviorSubject`ReplaySubject`有些類似,但不同的是AsyncSubject只會存儲數據流里的最后一條數據, 而且只有在數據流complete時才會將值發布出去。
  AsyncSubject主要是用來處理異步操作,當數據源是異步請求或者事件處理時,可能會發射出很多數據,如果我們只希望數據源的異步操作完成的時候,訂閱者才能接收到值,這個時候就可以使用AsyncSubject了。
  接下來我們看個例子,
  創建一個AsyncSubject, 然后發射數據,創建訂閱者,再發射數據。。。

let subject4: AsyncSubject<number> = new AsyncSubject<number>(); subject4.next(100); subject4.next(100); subject4.subscribe((res: number) => console.info("async-subjectA ", res)); subject4.next(300); subject4.subscribe((res: number) => console.info("async-subjectB ", res)); subject4.next(400); subject4.subscribe((res: number) => console.info("async-subjectC ", res)); subject4.complete(); subject4.subscribe((res: number) => console.info("async-subjectD ", res)); subject4.next(500);

  最后的結果就應該是:

//output4 async-subjectA 400 async-subjectB 400 async-subjectC 400 async-subjectD 400

  由于subject4是AsyncSubject, 只有在complete的時候才會向訂閱者publish數據,而且只publish最后一次數據,所以無論訂閱者何時訂閱數據源,都可以接收到最后一次數據。
  但為什么沒有打印出500呢,因為數據源已經complete了,你就無法再發射新數據了。

總結

  最后來總結一下四種Subject的特點,理解好的各自的特點,在項目開發中可以處理很多棘手的需求,同時也會避免很多問題的發生。

轉載于:https://www.cnblogs.com/lnlvinso/p/11228724.html

創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎

總結

以上是生活随笔為你收集整理的【Rxjs】 - 解析四种主题Subject的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。