Clean the operators’ chain in RxJS, RxSwift, or RxJava.

Keep clean the operators’ chain

An operators’ chain is a powerful tool for orchestrating tasks. Keeping the definition of the operator chain legible and clean allows for a better understanding of organized responsibilities. Consider the following example:

Example code 1 with RxJava.

network.getToken("api-key")
.concatMap(token -> cache.storeToken(token)
.concatMap(saved -> network.getUser(username)))
.subscribe(user -> Log.d(TAG, "User: " + user));

The objective of the previous code snippet is to orchestrate a task that obtains a token, then caches it, and then proceeds to query the user. That code is valid; however, it could be improved in the following way:

Example code 2 with RxJava.

network.getToken("api-key")
.concatMap(token -> cache.storeToken(token))
.concatMap(saved -> network.getUser(username))
.subscribe(user -> Log.d(TAG, "User: " + user));

What is the difference between code example 1 and code example 2?

Code in Example 1 is often used to orchestrate tasks with result dependencies, that is, when the next task (downstream) requires the results of the previous task (upstream).

In example 1, getUser operation does not need the results of the previous actions: the results of getToken or storeToken. For this reason, the code in example 1 can be replaced by the code in example 2 and clearer.

Now we show a case where the dependency on results is necessary:

Example code 3 with RxJava.

network.getToken("api-key")
.concatMap(token -> cache.storeToken(token)
.concatMap(saved -> network.getUser(username, token)))
.subscribe(user -> Log.d(TAG, "User: " + user));

getUser task needs the result of one of the previous tasks: the token in this case. Therefore an internal concatenation is used to gain access to the value since otherwise, the token variable would be unknown and would generate an error.

However, in these cases of task dependency, it is also possible to flatten the operations. That is possible through Tuplas like so:

Example code 4 with RxJava.

network.getToken("api-key")
.concatMap(token -> cache.storeToken(token)
.map(saved -> new Pair<>(token, saved)))
.concatMap(pair -> network.getUser(username, pair.first))
.subscribe(user -> Log.d(TAG, "User: " + user));

A transformation is used with the map operator to generate and propagate a tuple with the necessary values to the next task.

When the results of a task do not influence the execution of the following tasks, the result could be ignored. For example, in the following code:

Example code 5 with RxJava.

network.getToken("api-key")
.concatMap(token -> cache.storeToken(token))
.ignoreElements()
.andThen(network.getUser(username))
.subscribe(user -> Log.d(TAG, "User: " + user));

getUser task by not relying on the results of the previous tasks could ignore the elements.

What about RxJS?

Well, It's the same recommendation. See the next code:

Example code 1 with RxJS.

this.network.getToken("api-key")
.pipe(
concatMap(token => this.cache.storeToken(token)
.pipe(saved => this.network.getUser(username)))
)
.subscribe(user => console.log(user));

Example code 2 with RxJS.

this.network.getToken("api-key")
.pipe(
concatMap(token => this.cache.storeToken(token)),
concatMap(saved => this.network.getUser(username))
)
.subscribe(user => console.log(user));

What about RxSwift?

Also, It's the same recommendation. Check the next code:

Example code 1 with RxSwift.

network.getToken("api-key")

            .concatMap { token in self.cache.storeToken(token)

                .concatMap { saved in self.network.getUser(username) }

        }

        .subscribe(onNext: { user in print(user) })

        .disposed(by: disposeBag)


Example code 2 with RxSwift.

network.getToken("api-key")

            .concatMap { token in self.cache.storeToken(token) }

            .concatMap { saved in self.network.getUser(username) }

            .subscribe(onNext: { user in print(user) })

            .disposed(by: disposeBag)


If you want to find more information about RxJS, RxSwift or RxJava, I recommend you check the guide book:

The Clean Way to Use Rx. Also the Spanish version


Happy reading.



Previous
Next Post »
Thanks for your comment