昨天稍微介紹Subject的用途,今天進一步來介紹他的兄弟姐妹,共有6種,看起來很多,但仔細看就會發現差不多那幾個字組合而已,下面聽我娓娓道來,Relay因為篇幅關係,我們拿到明天再補充
昨天有稍微提到,PublishSubject定義『開始是空的,只會發送新的元素給訂閱者』,畫成圖會像下面這樣,訂閱者在數字1之後訂閱,只能等到再次發送數字2,才可以收到。
寫成程式碼如下,大家可以執行看看
let subject = PublishSubject<String>()
subject.onNext("1")
// 1, 2
subject
.debug("A")
.subscribe()
.disposed(by: disposeBag)
subject.onNext("2")
subject.onNext("3")
subject
.debug("B")
.subscribe()
.disposed(by: disposeBag)
// 3
subject.onError(NSError(domain: "Test", code: -1, userInfo: nil))
執行結果如下
A -> subscribed
A -> Event next(2)
A -> Event next(3)
B -> subscribed
A -> Event error(Error Domain=Test Code=-1 "(null)")
Unhandled error happened: Error Domain=Test Code=-1 "(null)"
A -> isDisposed
B -> Event error(Error Domain=Test Code=-1 "(null)")
Unhandled error happened: Error Domain=Test Code=-1 "(null)"
B -> isDisposed
.subscribe(onNext, onError)
,而是改用.debug()
,.debug()
顧名思義是在除錯時候使用,他可以把訂閱的開始到結束都印出來,帶入的String代表他的名稱,實際使用上可以使用emoji,視覺上圖片比文字能更快速辨認(但it邦好像不能使用emoji...,這裡替換成數字跟英文字母).error
而disposed。如果你要一訂閱就拿到上一次的值,可以使用BehaviorSubject,它定義是這樣的『開始是預設值,發送目前的最後一個值給訂閱者』,也就是說你不管什麼時候訂閱,都會有元素可以收到(至少有預設值)。
寫成程式碼如下,在建構BehaviorSubject需要再多給一個預設值
let subject = BehaviorSubject<String>(value: "1")
subject
.debug("A")
.subscribe()
.disposed(by: disposeBag)
subject.onNext("2")
// 2
print("Subject value: \(try! subject.value())")
subject.onNext("3")
subject.onError(NSError(domain: "Test", code: -1, userInfo: nil))
subject
.debug("B")
.subscribe()
.disposed(by: disposeBag)
// 3
print("Subject value: \(try! subject.value())")
執行結果如下
A -> subscribed
A -> Event next(1)
A -> Event next(2)
Subject value: 2
A -> Event next(3)
A -> Event error(Error Domain=Test Code=-1 "(null)")
Unhandled error happened: Error Domain=Test Code=-1 "(null)"
A -> isDisposed
B -> subscribed
B -> Event error(Error Domain=Test Code=-1 "(null)")
Unhandled error happened: Error Domain=Test Code=-1 "(null)"
B -> isDisposed
Fatal error: 'try!' expression unexpectedly raised an error: Error
.value()
這個func可以使用,他可以取的目前最新的元素,考慮到有Observable可能是.error
或是disposed,所以會throws RxError,這邊使用try!單純只是作為範例展示。.error
哦!Subject value:
在第一次會收到.next(2)
,第二次因為收到.error
而throws錯誤如果你要一訂閱就拿到上n次的值,那你要選擇ReplaySubject,它定義是『開始時給訂一個暫存大小(buffer size),發送時會將最後的n個元素存進暫存,並將暫存的元素發給訂閱者』,下圖就是以bufferSize = 2 的情況。
寫成程式碼如下,建構時需要給定bufferSize
let subject = ReplaySubject<String>.create(bufferSize: 2)
subject.onNext("1")
subject.onNext("2")
subject.onNext("3")
// 1
subject
.debug("A")
.subscribe()
.disposed(by: disposeBag)
subject.onNext("4")
subject.onNext("5")
subject.onError(NSError(domain: "Test", code: -1, userInfo: nil))
// 2
subject
.debug("B")
.subscribe()
.disposed(by: disposeBag)
執行結果如下
A -> subscribed
A -> Event next(2)
A -> Event next(3)
A -> Event next(4)
A -> Event next(5)
A -> Event error(Error Domain=Test Code=-1 "(null)")
Unhandled error happened: Error Domain=Test Code=-1 "(null)"
A -> isDisposed
B -> subscribed
B -> Event next(4)
B -> Event next(5)
B -> Event error(Error Domain=Test Code=-1 "(null)")
Unhandled error happened: Error Domain=Test Code=-1 "(null)"
B -> isDisposed
.error
(或 .completed
),所以這裡才是接收到4、5和.error
,這是跟前面兩種Subject比較不同的。本來昨天說要探討一下Subject的使用時機,但發現講完前三個Subject類型,篇幅好像就有點多了?留在明天或後天講好了!就這樣,掰掰