Another take on the really good answers already above — by way of an example.
Say that you have a class that returns an Observable based on its internal state(written in a pseudo Javascript like language, but applies to all ReactiveX implementations)
class DownloadManager {
var uuid = nil // this only gets set during runtime...say when a user performs a certain action
// fetches some data from the server.
func get() -> Observable<Data> {
if uuid == nil {
return .error(new DownloadUuidEmptyError())
}
return network.download(uuid, ...) // do something with the non nil uuid
}
}
Written this way, the method might be called, and the observable passed around before it actually gets evaluated, and uuid might not be present at time of method call, but present by the time the Observable is subscribed to, yielding an error.
let observable = manager.get()
// ... at some point, uuid is assigned to
// then we subscribe to our observable ...
observable.subscribe(...).disposedBy(bag) // errors!
In this situation, defer can come in handy to ensure that the evaluation(of uuid, for example) does not happen until subscription time.
// fetches some data from the server.
func get() -> Observable<Data> {
return Observable.defer {
if uuid == nil {
return .error(new DownloadUuidEmptyError())
}
return network.download(uuid, ...) // do something with the non nil uuid
}
}
Now, the above example will no longer error out. Perhaps the bigger goal is to ensure that your code can never reach this state, but sometimes it is not practical. This pattern has come in handy for me.