RxCaseStudy:
Default value after a countdown

Recently somebody asked me how he can send a default value if the stream hasn’t sent a new value in 5 minutes using RxSwift.

The final solution is short, however it uses few operators like merge, concat & flatMapLatest together which makes it more … advanced usage of Rx.

I thought it would be a great case-study for an article. So here it is! Enjoy reading 📚💪


Description

So… ones again… Imagine you have an Observable which constantly sends events from time to time. However, if the delay between 2 next events is too big you want to send a default value.

To create a countdown you can use the interval operator. This is easy:

Now you need to combine the timer with the original Observable. What’s more, you need to invalidate the old timer and run a new one if the original Observable sends an event. flatMapLatest is the operator which we are looking for:

of, just & concat – Not too many? 😱

flatMap transforms the Observable by sending events from inner Observable as an output. If you had return only the defaultValueIfIdle inside the flatMapLatest you would lose the event emitted by originalObservable.

concat allows you to connect multiple Observables into a single one. It subscribes to Observables when previous Observable sends complete. In our case flapMapLatest sends the item (from .just()) and then it starts the timer.

Observable.just is the easiest why to create an Observable with single value. It sends the given value as next event always followed by completed. You can read more about just operator in this article.

Since you use the flapMapLatest not just the flatMap, it will timer will invalidate the timer if an event comes before the countdown finish 🙌 🎉.

Countdown before first event

Right now the countdown starts after the first event from originalObservable. It would be nice to have the countdown also earlier:

You can just listen for the timer and invalidate it with takeUntil when originalObservable sends the first event.

After all, you need to take care of one thing more. Right now you have 2 different subscriptions of originalObservable. You use it as a parameter of takeUntil and also observableWithDefaultValue derives from it.

It would be nice to share events between these two subscriptions. You can just use share on originalObservable

Summary

flatMapLatest is a powerful operator which can be used to invalidate previous Observables. What’s more, you can use it in a combination of concat (or merge) to create custom sequences.

If you liked the article, don’t forget to share it on Twitter or on other social media 😉

You Might Also Like