0

@szilanor/stream - npm

 2 years ago
source link: https://www.npmjs.com/package/@szilanor/stream
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Stream API

Type-safe API for processing iterable data in TypeScript and JavaScript similarly to Java 8 Stream API, LINQ or Kotlin Sequences. Unlike RxJS this library is not asynchronous, you get an immediate result without any subscription or await call.

If this library makes your life easier or your boss happier, and you want to support my work then you can always thank me with a free coffee.

Getting started

npm install --save @szilanor/stream

Alternatively use Stream from CDN by adding this to your HTML:

<script src="https://unpkg.com/@szilanor/stream/"></script>

Classic Javascript solution

const result = [1, 2, 3].filter(x => x % 2 === 0).map(x => x * 2);

Stream API solution

Creating a Stream object

import {Stream, of, from} from '@szilanor/stream';

let stream: Stream<number>;
stream = new Stream([1, 2, 3]); // With constructor;
stream = of(1, 2, 3); // With the 'of' creator function
stream = from([1, 2, 3]); // With the 'from' creator function

Operations on stream entries for the same result

import {filter, map, compound} from '@szilanor/stream';

// Chaining pipe functions
stream = stream.pipe(filter(x => x % 2 === 0)).pipe(map(x => x * 2));

// Using the 'compound' operation
stream = stream.pipe(
  compound(
    filter(x => x % 2 === 0),
    map(x => x * 2)
  )
);

Process the stream for the same result

import {toArray} from '@szilanor/stream';

// Using for..of
let result = [];
for (let entry of stream) {
  result.push(entry);
}

// With a collector
result = stream.collect(toArray());

Why Stream API?

  • Can achieve faster results
/* 
 * Since the API is using Javascript Iterables the operations are applied 
 * to the entries one bye one in order. In this example we know the 
 * answer after the second element, so it is unnecessary to map everything 
 * first. 
 */

let allEven: boolean;
const input = [1, 2, 3, 4, 5];

// Classic JS maps all the entries first then returns false
allEven = input.map(x => x + 1).every(x => x % 2 === 0);

// vs Stream API maps only the first element then returns false
allEven = from(input)
  .pipe(map(x => x + 1))
  .collect(all(x => x % 2 === 0));

Benchmark file based on this example

Classic JS x 1,833 ops/sec ±0.25% (94 runs sampled)
Stream API x 123,688 ops/sec ±1.19% (88 runs sampled)
Fastest is Stream API
  • More readable code
import {from, distinct, collect} from '@szilanor/stream';

// Filtering duplicates and group them by whether they are even or odd
const input = [1, 1, 1, 1, 2, 3, 4, 4, 5];

// Classic JS
const resultClassic: Map<string, number[]> = new Map<string, number[]>();
Array.from(new Set<number>(input)).forEach(x => {
  const key = x % 2 === 0 ? 'even' : 'odd';
  resultClassic.set(key, [...(resultClassic.get(key) || []), x]);
});

// Stream API
const resultStreamApi: Map<string, number[]> = from(input)
  .pipe(distinct())
  .collect(groupBy(x => (x % 2 === 0 ? 'even' : 'odd')));
  • You can create your own operators / collectors if you don't find what you need
import {CollectorFunction, OperationFunction} from '@szilanor/stream';

const myAwesomeCollector: CollectorFunction<unknown, unknown> = { /* your own implementation */ };
const myAwesomeOperation: OperationFunction<unknown, unknown> = { /* your own implementation */ };

const result = of(1, 2, 3)
  .pipe(myAwesomeOperation())
  .collect(myAwesomeCollector());

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK