Search code examples
rxjsrxjs5rxjs-lettable-operators

creating lettable rxjs "string.split" operator


I am attempting to do some string manipulation in rjxs, and while I can accomplish it with the built in behaviors on the string class and the array class in Javascript, I'm wanting to use this as an exercise to learn even more about rxjs and understand a fluent code-flow better.

To that end, it's imperative to me that I discover a way to do it that can fit in a fluent solution, instead of a series of variable assignments like I see in most rxjs examples.

Essentially, here's the situation; I've got a string of text;

const example = `
    key || value
    key || value
    key || value

    value
    value

    value
    key || key[key1] = value | key[key2] = value
    key || value
`;

The first thing that I need to do is use string.split('\n') to create an array of strings, so that I can through each line and perform further operation.

example.string.split('\n') does give the desired results, but trying to send this into rxjs begins to get rather mixed yield. With the pipe method, I know that I send the results into rxjs as an Observable, but I'm having a really troubling time grasping how to truly treat it from there without excessive nesting into the map operator.

For example, if I do ...

of(example.string.split('\n')).pipe(
   map(results => results.toString().split('||')),
   map(results => ... ),
   ...
).subscribe();

I can start to get a semblance of what I'm looking for, but what I'd really like to do is ...

of(example).pipe(
   split('\n'),
   split('||'),
   concatMap(results => ...)
).subscribe();

Reading the documentation on lettable operators, seen here, it looks like this should be a pretty easy thing to create. In theory, it should look like this in my mind;

const split = (separator: string) => <T>(source: Observable<T>) =>
    new Observable(observer => {
        source.subscribe({
            next(x) { observer.next(x.toString().split(separator)); },
            error(err) { observer.error(err); },
            complete() { observer.complete(); }
        })
    });

So that should make the whole code obvious enough;

of(example).pipe(
    split('\n')
).subscribe(result => console.log(`[n]::${result}`));

But this doesn't give me what I really expect. I expected to get an array of the lines, but if I output it, I get ...

[n]::, key || value, key || value, key || value, ,
value, value, , value, key || key[key1] = value | key[key2] = value, key || value,

I'm really unclear what I'm doing wrong, here. Since it's hard to demonstrate rxjs in most of the code playgrounds like plunkr or jsfiddle, at least to my knowledge, I've prepared a playground environment to demonstrate my work on stackblitz, if it helps.

You'll find all of the pertinent code in the playground/index.ts file. I've done the best I can to abstract away the need to have any knowledge of angular, as I've painstakingly earmarked the sections that should be left alone to make it continue showing output on the right side. If you do not know angular, but can help with rxjs, you should be able to work without ever disturbing that setup.

STACKBLITZ PLAYGROUND


Solution

  • Your code is working fine, just the es6 template string ${} flattened your array into a string. If you console.dir or log the result, you will see a correct array retrieved.