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 😉