Hey RxSwift Observable, are you loading?

Adding loading information to your RxSwift streams

Sometimes you know a given operation is going to take a while, it can be a network call (especially on mobile, with bad network conditions), heavy image processing, or even when getting the user’s location with Core Location.

In that case, most of the time, a loader needs to be displayed somewhere on the screen.

It’s easy to design how we would displaying the loader in an imperative programming world:

However, things might be different if we try to stick with the philosophy of reactive programming:

How would you create an Observable<Bool> that emits true when the network request is in progress, and false when it finishes, just using the getMe() function?

The Dø approach

A first naive approach would be to use the .do() operator and hack your way into building the desired Observable<Bool> stream.

Since it’s modifying the state of an external resource (here rx_isLoading), the .do() operator has a side effect. It works just fine, but wouldn’t it be better to get rid of side effects and keep working with pure streams? Yes it would!

Introducing `.monitorLoading()`

Recently, I thought about how to avoid any side effects from the Dø approach.

I ended up writing an extension that adds a monitorLoading() function to any ObservableType. With it, developers can compute 3 different streams by calling:

  • .data() to return a stream emitting the final result of the operation.
  • .loading() to return a stream emitting a Bool to know if the operation loads or not.
  • .error() to return a stream emitting an Error when the operation fails.

The result is elegant, and simple to use:

From there, its easy to know when the request loads enabling you to show or hide the loader as needed:

Plus, the extension provides an API in case the network call failed with an error. It’s accessible by calling .error() on the result of .monitorLoading().

I won’t spend time on the implementation details of the .monitorLoading() extension, but here are the results, feel free to use and improve it!

Thanks for reading! If you liked what you read, feel free to share or leave a comment. You can also follow me on Twitter.