When we learn a new programming language or new frameworks we always do some mistakes. This is how we people learn things.
In this article, I’m want to show you my top 7 mistakes which I did during my Rx trials. I hope I will help you to avoid them 🙂.
#1 – combineLatest vs withLatestFrom
This is the mistake everyone does I think :P. It’s very important to remember
combineLatest sends events when any of its inner Observables sends an event. So… when you want to respond to button tap is the wrong idea to mix it in
If you want to read more what are the differences between
zip you can find an article here 🙂.
#2 – Observable should be lazy
Observable by its nature is a lazy sequence. It shouldn’t run any logic until a subscription. Sometimes you need to wrap an existing API within an Observable:
It’s fine to use
just to wrap a single value. However, you run all the logic to calculate the value before a subscription. If you have used
deferred the calculation would be moved until some Observer subscribes to your Observable:
You can read more about
#3 – Using wrong DisposeBag
DisposeBag is an awesome tool to store multiple
Disposable and dispose them at
deinit. However, it’s crucial to consider when do you want to cancel old subscriptions.
Typical use-case of that is binding the cell with data from CellViewModel:
The above example my looks fine, but there is a big bug inside. Since we’re adding the disposable into
self.disposeBag you gonna have multiple outdated subscriptions when a user starts scrolling the tableView.
You should add the
disposable into cell’s disposeBag and deallocate it on cell reusing (you need to override
#4 – Not using drivers on UI
Traits are awesome because they help communicate and ensure in compile time our assumptions. Take a
Driver for example. Its main purpose is to be used at the UI part of the application.
I obey a rule that all sequences which
UIView subscribes to should be a
With Rx, it’s very easy to change a queue/thread. "With Great Power Comes Great Responsibility" Uncle Ben used to say. As a result, sometimes you can change the thread by a mistake and forget to call
observeOn(MainScheduler.instance) before touching the UI. As a result, you have a crash… 💥
If you use Driver instead, transforming an Observable into
Driver automatically adds
observeOn(MainScheduler.instance). You don’t need to remember about it.
Small change inside the interface of the protocol protects the app from any unexpected thread changes and crashes…
#5 – Error handling
Observable is terminated whenever it sends
error event. It is one of the Observable traits. When I read this for the first time I didn’t see what are the consequences.
flatMap sends all the events from given Observable into the "original" pipe. All is the key word here. It forwards next events and errors as well.
login function throws an error
flatMap forwards the error into to the main sequence which is the
loginAtButtonTap. Whenever an Observable sequence sends an error it stops sending new items. As the result, the app will stop responding to button taps.
To prevent terminating of
loginAtButtonTap you can for example use
Result<T> type to have an
Observable<Result<User>> or to use
materialize(). You can read more about errors in RxSwift here.
#6 – Subscribing multiple times into 1 Observable
Observable is immutable class. Every operator returns a new Observable object and doesn’t modify the original. However, sometimes you need to share the results between few Observables, for example:
itemsProvider calls a REST API to receive items the above code would call the request twice. When you subscribe to
numberOfItems you would call
itemsProvider twice because
count are 2 different Observables.
To share the results from
itemsProvider you should use
#7 – Overusing subjects & variables
Variables and Subjects are a great tool, however, their usage should be limited. I don’t want to say you should avoid them at all cost, however, remember when you use subjects & variables you use a "mutable variables" in Rx world.
Subjects are the "mutable variables" of the Rx world and in most cases you do not need them. – Erik Meijer
Remember that most of the time you can replace Subject with some operators like
defer and many others. If you want to read more when you should use a subject and when you should not I can recommend you this article however it is from Rx.NET world.
Title image – Flickr – becca.peterson26