Skip to content

Instantly share code, notes, and snippets.

@bobspryn
Last active January 24, 2017 16:21
Show Gist options
  • Save bobspryn/ab56929c6aa4fd9f9b085d82f45fa43e to your computer and use it in GitHub Desktop.
Save bobspryn/ab56929c6aa4fd9f9b085d82f45fa43e to your computer and use it in GitHub Desktop.
//: Playground - noun: a place where people can play
// One way or another get RxSwift into your playground: https://github.com/segiddins/ThisCouldBeUsButYouPlaying
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
import RxSwift
// this is for testing using shareReplay for our network calls and any gotchas
// comment out various portions to understand behavior
// I wanted to understand the behavior of what happens when subscribers go from 1 -> 0, and then 0 -> 1 again
// `shareReplay` has special behavior of disposing it's internal subscription when it's own subscribers
// go from 1 -> 0. I wanted to make sure in the weird scenario where a new subscriber was added late
// we weren't causing a new network call. A regular `replay` would prevent this because it wouldn't ever
// dispose of it's internal subscription during it's lifetime. But that also means that network requests wouldn't
// cancel in most scenarios, even if the `ConnectedObservable`s subscribers were disposed of
//
// The results show that as long as the network request observable calls `onCompleted()` after `next`, that
// `shareReplay` won't kick off a new network request even if new subscribers are added after the first subscriber
// is disposed. Lack of `onCompleted()` would cause the network request to occur again.
func shareReplayVersusRegularReplay() {
// Create an observable as our proxy for a network request
let test = Observable<Int>.create { (observer) -> Disposable in
print("Creating")
let queue = DispatchQueue.global(qos: .userInitiated)
// simulating a network call by delaying the work
let item = DispatchWorkItem(block: {
print("Running")
observer.onNext(1)
// since this work completes, this won't be called a second time via shareReplay on subsequent subscriptions,
// even after the initial one is completed
// comment out to see shareReplay calling this block a second time when it doesn't complete (subscribers see the existing
// value and trigger a new one)
observer.onCompleted()
})
queue.asyncAfter(deadline: .now() + 0.5, execute: item)
// for testing when things get disposed
return Disposables.create {
print("Disposing")
item.cancel()
}
}
// Immediately creates a subscription and causes the work to be added to the queue
// does not dispose of the internal subscription when the external goes to zero (web service won't cancel)
// one benefit is that the network call would never be called again in the situation where it hasn't completed
// (but the network call should always "complete" if a "next" event has been sent, this is isn't really a big benefit)
// let replayer = test.replay(1)
// replayer.connect()
// share replay disposes the internal subscription when it's subscribers go to zero where as `replay` above does not
let replayer = test.shareReplay(1)
let sub = replayer.take(1).subscribe { (value) in
print("first \(value)")
}
// simulate a disposeBag being disposed
// work should never occur
// comment out to see how the "work" doesn't occur on subsquent subscriptions (normal replay behavior), only the first time
sub.dispose()
// uncommenting these lines will show how the "work" doesn't occur multiple times with `shareReplay`
// as long as the work event is calling `onCompleted()`. Commenting out the `onCompleted()` event will cause
// the work to occur multiple times on new subscriptions like these if the previous subscription has been disposed
// DispatchQueue.main.asyncAfter(deadline: .now() + 2) { // in half a second...
// print("delay")
// let _ = replayer.take(1).subscribe { (value) in
// print("second \(value)")
// }
// let _ = replayer.take(1).subscribe { (value) in
// print("third \(value)")
// }
// }
}
shareReplayVersusRegularReplay()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment