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()
.
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 tojust()
but creates an Observable with given errorempty()
– it returns an Observable which caries only acompleted
eventnever()
– 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 π.