TimeRange — RxJS custom function that emits a set of values in specified timeouts

Oleksandr - Sep 23 '19 - - Dev Community

TimeRange — RxJS custom function that emits a set of values in specified timeouts

Why, how and where for those who like RxJS :-)

Customizing RxJS (Photo by Sneaky Elbow)

Prerequisites: I assume you knwo RxJS and have some practice with it. If you are new to it or want to learn some advanced topics - watch my video-course " Hands-on RxJS for Web development " on Udemy.

Why

Periodically in my development practice, I meet situations when you have to emit a few values in specified timeouts.

For example:

  1. To show and then hide some splash-message:

Managing splash-message show/hide timeouts

  1. To do some nice animations

Managing appearance timeouts

  1. Or even just emit values for unit tests (yeah, I know about marbles, but sometimes I just want to check final value, period:)

Simple code for auto-complete with debounce — demands providing values with specific timings to be tested

So how it can be implemented? Ok, let's review some scenarios:

How to implement?

Ugly way

Ok, the simplest way — to run many setTimeout's, like this:

OK, not so bad, but what if I want to show more elements in different delays?

Looks oldschool and ugly. Can we do better?

Ugly way, part 2

Lets use RxJS now and try to implement it:

This code doesn't allow absolute delay (when the next emission is delayed against start/subscription moment).

To implement absolute delays approach (all delays are specified against subscription/start moment) we can use mergeMap instead of concatMap:

Looks like a lot of code, and also delays are hardcoded. We can do better. So let's go further!

Editor choice method

Ok, we already know that hardcoding values/delays is not reusable, and we also want to be able to schedule in relative (delayed against previous emissions) and non-relative/absolute (delayed against subscription moment) way. Taking all the above into account, I implemented a custom timeRange function.

Custom timeRange function.

Benefits:

  1. Looks nice and compact.
  2. Allows both absolute and relative delays to be specified.

OK, now let's show three use-cases I mentioned previously.

Where to use it

#1 Splash-message control example

Here it implementation code:

What do we do here?

  1. Emit two values with 1000 and 2000 delay (values don't play any role here, actually only timings matter)
  2. The first value will show splash element with a message.
  3. Second will hide it (using .classList.toggle('show'))

Here is how it works:

You can play with it in a codepen here.

#2 Animating a few elements subsequent appearance

Here is the code:

We just grab a set of elements and then show them one by one with specified timeouts on each range$ Observable emission.

Here is the result:

You can check the code here.

#3 Mocking input params for unit tests code with timeRange.

How it works:

  1. We mock ajax.get with a function that will return value '42' asynchronously (emulation of network request)
  2. Then se debounce time = 15ms.
  3. After that call getSearchResult with mocked input$ as a param and subscribe (to start the process).
  4. input$ will emit three values with delays 1ms, 5ms, 30ms. Since debounceTime is set to 15ms, only second and third values will cause network request to be called (ajax.get in our case);

And result:

The code and the test can be found here.

Conclusion

I've added timeRange function to my rxjs-toolboxlib. It is not big for now. You can read more about it here: ‘forkJoin’ with the progress of completion

Have your own interesting RxJS solutions? Mention them in comments!

Like this article? Let's keep in touch on Twitter.

Want to learn more about RxJS? Give a try to my video-course "Hands-on RxJS". It contains both total beginners content and more advanced topics as well.

Cheers.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player