Last active
January 24, 2017 16:21
-
-
Save bobspryn/ab56929c6aa4fd9f9b085d82f45fa43e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//: 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