TLD
TLD

Reputation: 8135

Difference between Observable.defer and Observable.create in java rx

Can someone explain me the difference between defer and create methods in Observable? I failed to understand when I should use defer and when should I use create ..

REFERENCES:

Defer: http://reactivex.io/documentation/operators/defer.html

Create: http://reactivex.io/documentation/operators/create.html

Thank you

Upvotes: 38

Views: 22875

Answers (3)

Bob Spryn
Bob Spryn

Reputation: 17812

So the distinction seems to be: defer is good when you have something that creates/returns an observable already, but you don’t want that process to happen until subscription.

create is good when you need to manually wrap an async process and create an observable. That creation is also deferred until subscription.

To put it another way:

defer is an operator that enables deferred composition of observable sequences.

create is a custom implementation of observable sequence (where creation is deferred until subscription).

So if you have a situation where you might use just to create an Observable from some results/value or you have a network API layer that returns an Observable of the request, but you don't want that request to kick off until subscription. defer would be good for those scenarios.

If you have a network API layer that doesn't return an Observable for a request, but which you need an Observable interface to, you might use create. That Observable sequence still wouldn't be created until subscription though. If you wanted that network call to kick off regardless of subscription, then you would use a different mechanism, like a Subject, potentially that replays.

Upvotes: 33

Ying
Ying

Reputation: 1990

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.

Upvotes: 0

Dennis R
Dennis R

Reputation: 1937

create(...) actually creates Observable immediately.

    public final static <T> Observable<T> create(OnSubscribe<T> f) {
        return new Observable<T>(hook.onCreate(f));
    }

defer(...) accepts Factory function that returns Observable(Subject, etc...), wraps it with OnSubscribeDefer and creates Observable only when subscriber subscribes, new Observable for every subscriber.

public final static <T> Observable<T> defer(Func0<Observable<T>> observableFactory) {
    return create(new OnSubscribeDefer<T>(observableFactory));
}

See some more details here

Upvotes: 20

Related Questions