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:
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
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
completed. Usually you will send
completed (one after another) or
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
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
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
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.
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.
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.
deferredhas one trait which you need to remember about.
deferredcreates 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.
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
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
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 😉.