RegExp syntax for Observables: Never Been Easier!

kosich

Kostia Palchyk

Posted on December 23, 2019

RegExp syntax for Observables: Never Been Easier!

Imagine we need to implement a drag-n-drop behavior.

For that, we have three event streams: mousemove$, mousedown$, mouseup$. So we want to capture mousemove$ events after mousedown$ emitted and before mouseup$.

Let's draw a marble diagram of the event streams we have:

mousedown$  --o------------
mousemove$  -o-o-o-o-o-o-o-
mouseup$    ------------o--
Enter fullscreen mode Exit fullscreen mode
Every event stream is represented with separate line.
o stands for event on the stream. - is a separator to represent passing time

For better readability let's substitute all the os to respective letters of the streams:

mousedown$  --d------------
mousemove$  -m-m-m-m-m-m-m-
mouseup$    ------------u--
Enter fullscreen mode Exit fullscreen mode
'd' will now stand for mouse-down event, 'm' for mouse-move, 'u' for mouse-up

Now that we have distinct event names, we can simplify our diagram to a single line of events:

events$     -mdm-m-m-m-mum-
Enter fullscreen mode Exit fullscreen mode

Let's remove the time - signs as well, we don't them:

events$      mdmmmmmum
Enter fullscreen mode Exit fullscreen mode

Okay, to rephrase our task in terms of the new diagram: we need to capture the m events between d and u emissions.

πŸ€”

Hmm...

"we need ms between d and u"...

Sounds familiar...

Ah! If that was a string, we could easily do it with a regular expression:

/dm*u/.exec('mdmmmum')
Enter fullscreen mode Exit fullscreen mode

Would give us the needed dmmmu without trailing mouse-move m events...

Right?

If only we had a library to select events from streams with regexes...

🀩 Introducing Regular Expressions for Rx

With exprs-rx package you can now query your streams with regular expressions like syntax!

mousedown$  --d------------
mousemove$  -m-m-m-m-m-m-m-
mouseup$    ------------u--

                 dm*u

result$     --dm-m-m-m-mu|
Enter fullscreen mode Exit fullscreen mode

Benefits:

  • clear and extensible syntax
  • no need to remember dozens of operators
  • no need to import them, which reduces bundle size
  • with more implementations to come β€” one syntax for all stream libraries (monetjs, kefirjs, baconjs, TC39 Observables, etc)

Example

Here's our drag-n-drop example in JS:

import { exec } from 'exprs-rx';

const item = document.getElementById('item');

const D = fromEvent(item, 'mousedown');
const M = fromEvent(document, 'mousemove');
const U = fromEvent(document, 'mouseup');

exec(
  'DM*U'         // <- regular expression
  , { D, M, U }  // <- streams that will be used
)
  .pipe(
    // ... apply any operators ...
  )
  .subscribe(console.log);
Enter fullscreen mode Exit fullscreen mode

Repo //github.com/expressions-for-reactive-streams/js-rx-exprs

Currently, the library supports capital letters A-Z that represent a single emission of a corresponding stream.

And a repeat A* notation that will consume multiple events from the corresponding stream, until completion or until next entry in the regex matches.

And much more to come: (), [], !, etc!

For regex specification and plans on vocabulary, please, see this repo github.com/expressions-for-reactive-streams/spec-regular-expressions

Try it

Install it

npm i exprs-rx
Enter fullscreen mode Exit fullscreen mode

πŸ™Œ Outro

The idea is to extend the expressions syntax to cover 80% of routine RxJS tasks. And maybe add combination commands. The possibilities are endless!

For upcoming amazing updates β€” follow me here and on twitter

If you've found this post worth sharing β€” please, use this tweet:

πŸ™‚ Thanks!

πŸ’– πŸ’ͺ πŸ™… 🚩
kosich
Kostia Palchyk

Posted on December 23, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related