Creating an Observable: create, just, deferred

Creating an Observable: create, just, deferred

RxSwiftCommunity is great and has already developed great Rx wrappers for existing API in iOS/mac world. However, you will always find a library or framework which doesn’t have Rx extension yet.

ReactiveX offers you 3 operators which you can use to wrap not-reactive code within an Observable. These operators are:

  • create()
  • just()
  • deferred()

What is the difference between them and when you should use which? These are the questions which I want to answer for. Enjoy reading πŸ“šπŸ’ͺ

create() – the most flexible way to create an Observable

create() is probably the most flexible operator to create an Observable from our short list.

The reason why I called it the "most flexible" is that you can wrap any API you want to. It doesn’t matter if it is a synchronous or an asynchronous code. You have the absolute power when to send next, error or completed events.

create() takes a closure (AnyObserver<T>) -> Disposable as a parameter:

Inside the closure, you need to send at least one event to the observer. It can be next(), error() or completed. Usually you will send next() and completed (one after another) or error().

You’ve already had a chance to use Observalbe.create() in my previous articles. If you want to see more examples of using it I recommend you to read The practical introduction to RxSwift or Presenting the UIAlertController with RxSwift πŸ“š

just() – the easiest way to wrap a value

As I said before create() is the most flexible way to create the Observable.

However, if you want just to transform a single value into the Observable the just() is probably more readable option to choose. just() takes an argument and sends it as next and then it sends completed right after the next.

just() has also few siblings:

  • error() – it works similar to just() but creates an Observable with given error
  • empty() – it returns an Observable which caries only a completed event
  • never() – it returns an Observable which never sends event sto his observers

deferred() – defer calculation until subscription

just() is just a simple operator which wraps a single value.

However, the following line return Observable.just(doSomeMath()) will calculate the result of doSomeMath() before creating the Observable. It would be fine if the calculation is fast, but what if it isn’t… πŸ€”? The calculation can block your thread.

Moreover, just() has also one additional drawback. Sometimes you should read a value after the subscription. Take any iOS permission as the example:

The above code may not work as you want. You read the authorizationStatus while creating the Observable not when an observer subscribes to it.

Imagine a user changes the permission in iOS settings before an observer subscribes for the permissionObservable. The observer will receive the old value of the permission.

However, deferred is the operator which solves all of these problems:

deferred defers reading of the value until a subscription.

It means the observer will have a fresh permission status and your calculation will be calculated when the result is indeed needed.

deferred has one trait which you need to remember about. deferred creates the Observable from his closure each time it has a new observer. It means subscribing to permissionObservable() 2 times will create 2 Observable objects. It can affect the performance, however it’s not likely to happen πŸ˜‰.

Of course, there are many ways to handle these problems. deferred is just one of them which I’ve found to be handy.

The summary

Observable.create is the most flexible way to create a custom Observable however you have to remember about closing the stream (by sending the completed) and also about returning a Disposable.

Operators like just, error, empty or never may sometimes be enough to create an Observable you want to have and for sure they don’t force you to write so much boilerplate code πŸ™‚

However, sometimes you want to defer some slow calculations until an Observable has an active subscription. In such cases, you may use deferred.

I hope you like the article πŸ˜ƒ. If it so please share the article with your friends by clicking on share buttons below πŸ’ͺ.

See you next time πŸ˜‰.