itiriri-async

Build Status Coverage Status

Next generation library to manipulate asynchronous iterators.

import * as WebRequest from 'web-request';
import itiririAsync from 'itiriri-async';

type ToDo = {
  id: number,
  userId: number,
  title: string,
  completed: boolean,
};

async function* todosAsync() {
  let id = 1;
  while (true) {
    yield await WebRequest.json<ToDo>(`https://jsonplaceholder.typicode.com/todos/${id++}`);
  }
}

async function showTop2ToDos(): Promise<void> {
  const todos = await itiririAsync(todosAsync())
    .filter(x => !x.completed)
    .take(2)
    .awaitAll();

  console.log(todos.toArray());
}

showTop2ToDos();
// [ 'delectus aut autem', 'quis ut nam facilis et officia qui' ]

Check examples folder for more

Installation

Using npm:

$ npm install 'itiriri-async' --save

Importing:

import itiririAsync from 'itiriri-async';

Running tests

$ npm install
$ npm test

Complete list of methods

average

Returns the average value.

Syntax

average(): Promise<number>;
average(selector: (element: T, index: number) => number): Promise<number>;

Parameters

For a sequence with no elements returns undefined.

Example

import itiririAsync from 'itiriri-async';

async function* generator1() {
  yield* [41, 42, 43];
}

async function* generator2() {
  yield* [{value: 1}, {value: 2}];
}

itiririAsync(generator1()).average()  // returns Promise<42>
itiririAsync(generator2()).average(elem => elem.value) // returns Promise<1.5>

awaitAll

Awaits for all elements an returns IterableQuery. The ruterned iterable is a sync itiriri iterable.

Syntax

awaitAll(): Promise<IterableQuery<T>>

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [41, 40, 43];
}

// ...
const numbers = await itiririAsync(generator()).awaitAll();
// returns IterableQuery([41, 40, 43])

numbers.sort().toArray();
// returns: [40, 41, 43]

concat

Concatenates the sequence with another one.

Syntax

concat(other: T): AsyncIterableQuery<T>;
concat(other: Promise<T>): AsyncIterableQuery<T>;
concat(other: Iterable<T>): AsyncIterableQuery<T>;
concat(other: AsyncIterable<T>): AsyncIterableQuery<T>;

Parameters

Example

import itiririAsync from 'itiriri-async';

async function* generator1() {
  yield* [1, 2, 3];
}

async function* generator2() {
  yield* [4, 5];
}

(async function() {
  const q = await itiririAsync(generator1()).concat(generator2()).awaitAll();
  q.toArray();   // returns [1, 2, 3, 4, 5]
})();

(async function() {
  const q = await itiririAsync(generator1()).concat([2, 1]).awaitAll();
  q.toArray();   // returns [1, 2, 3, 2, 1]
})();

(async function() {
  const q = await itiririAsync(generator1()).concat(-1).awaitAll();
  q.toArray();   // returns [1, 2, 3, -1]
})();

concat is a deferred method and is executed only when the result sequence is iterated.

distinct

Returns a sequence of unique elements.

Syntax

distinct(): AsyncIterableQuery<T>;
distinct<S>(selector: (element: T) => S): AsyncIterableQuery<T>;

Parameters

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 2, 3, 3, 3, 4, 2];
}

(async function () {
  const q = await itiririAsync(generator()).distinct().awaitAll();
  q.toArray();   // returns [1, 2, 3, 4]
})();

distinct is a deferred method and is executed only when the result sequence is iterated.

entries

Returns a sequence of key/value pair for each element and its index.

Syntax

entries(): AsyncIterableQuery<[number, T]>;

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* ['Bob', 'Alice'];
}

(async function () {
  const q = await itiririAsync(generator()).entries().awaitAll();
  q.toArray();   // returns [[0, 'Bob'], [1, 'Alice']]
})();

entries is a deferred method and is executed only when the result sequence is iterated.

every

Tests whether all the elements pass the predicate.

Syntax

every(predicate: (element: T, index: number) => boolean): Promise<boolean>;

Parameters

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 4, 3, 0];
}

(async function () {
  await itiririAsync(generator()).every(x => x >= 0); // true
})();

(async function () {
  await itiririAsync(generator()).every(x => x > 0); // false
})();

exclude

Returns a sequence of elements not contained in a given sequence.

Syntax

exclude<S>(others: Iterable<T>): AsyncIterableQuery<T>;
exclude<S>(others: Iterable<T>, selector: (element: T) => S): AsyncIterableQuery<T>;

Parameters

Example

import itiririAsync from 'itiriri-async';

async function* generator1() {
  yield* [2, 0, 1, 8, 2];
}

async function* generator2() {
  yield* [{ id: 1 }, { id: 2 }];
}

(async function () {
  const q = await itiririAsync(generator1()).exclude([0, 1]).awaitAll();
  q.toArray(); // returns [2, 8, 2]
})();

(async function () {
  const q = await itiririAsync(generator2()).exclude([{ id: 2 }], x => x.id).awaitAll();
  q.toArray(); // returns [{id: 1}]
})();

exclude is a deferred method and is executed only when the result sequence is iterated.

filter

Returns a sequence of elements that pass the predicate.

Syntax

filter(predicate: (element: T, index: number) => boolean): AsyncIterableQuery<T>;

Parameters

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 2, 3, 4, 5];
}

(async function () {
  const q = await itiririAsync(generator()).filter(elem => elem < 3).awaitAll();
  q.toArray(); // returns [1, 2]
})();

(async function () {
  const q = await itiririAsync(generator()).filter(elem => elem > 10).awaitAll();
  q.toArray(); // returns []
})();

filter is a deferred method and is executed only when the result sequence is iterated.

find

Finds the first element that satisfies the specified predicate.

Syntax

find(predicate: (element: T, index: number) => boolean): Promise<T>;

Parameters

If no element satisfies the predicate, returns undefined.

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 2, 3, 4, 5];
}

(async function () {
  await itiririAsync(generator()).find(elem => elem > 2); // returns 3
})();

(async function () {
  await itiririAsync(generator()).find(elem => elem > 10); // returns undefined
})();

findIndex

Finds the first index at which a given element satisfies the specified predicate.

Syntax

findIndex(predicate: (element: T, index: number) => boolean): Promise<number>;

Parameters

If no element satisfies the predicate, returns -1.

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 2, 3, 4, 5];
}

(async function () {
  await itiririAsync(generator()).find(elem => elem > 2); // returns 2
})();

(async function () {
  await itiririAsync(generator()).find(elem => elem > 10); // returns -1
})();

findLast

Finds the last element that satisfies the specified predicate.

Syntax

findLast(predicate: (element: T, index: number) => boolean): Promise<T>;

Parameters

If no element satisfies the predicate, returns undefined.

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 2, 3, 4, 5];
}

(async function () {
  await itiririAsync(generator()).findLast(elem => elem > 2); // returns 5
})();

(async function () {
  await itiririAsync(generator()).findLast(elem => elem > 10); // returns undefined
})();

findLastIndex

Finds the last index at which a given element satisfies the specified predicate.

Syntax

findLastIndex(predicate: (element: T, index: number) => boolean): Promise<number>;

Parameters

If not present, returns -1.

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 2, 3, 4, 5];
}

(async function () {
  await itiririAsync(generator()).findLastIndex(elem => elem > 2); // returns 4
})();

(async function () {
  await itiririAsync(generator()).findLastIndex(elem => elem > 10); // returns -1
})();

first

Returns the first element in a sequence.

Syntax

first(): Promise<T>;

For an empty sequence returns undefined.

Example

import itiririAsync from 'itiriri-async';

async function* generator1() {
  yield* [1, 2, 3, 4, 5];
}

async function* generator2() {
  yield* [];
}

(async function () {
  await itiririAsync(generator1()).first(); // returns 1
})();

(async function () {
  await itiririAsync(generator2()).first(); // returns undefined
})();

flat

Returns a sequence with all sub-sequences concatenated.

Syntax

flat<T>(selector?: (element: T, index: number) => AsyncIterable<S>): AsyncIterableQuery<T>;

Parameters

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [[1, 2, 3], [4, 5]];
}

(async function () {
  const q = await itiririAsync(generator()).flat().awaitAll();
  q.toArray(); // returns [1, 2, 3, 4, 5]
})();

flat is a deferred method and is executed only when the result sequence is iterated.

forEach

Runs through every element and applies a given function.

Syntax

forEach(action: (element: T, index: number) => void): Promise<void>;

Parameters

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 2, 3];
}

(async function () {
  await itiririAsync(generator()).forEach(elem => console.log(elem));
})();
// 1
// 2
// 3

groupJoin

Returns a sequence of correlated elements where each element from the current sequence is matched with zero or more elements from the other sequence.

Syntax

groupJoin<TKey, TRight, TResult>(
    other: Iterable<TRight>,
    leftKeySelector: (element: T, index: number) => TKey,
    rightKeySelector: (element: TRight, index: number) => TKey,
    joinSelector: (left: T, right: TRight[]) => TResult,
  ): AsyncIterableQuery<TResult>;

Parameters

The joinSelector function is called on each element from the source sequence and the array of matched elements from the joined sequence.
When an element from the source sequence doesn’t match with any of the elements from the joined sequence, the joinSelector function will be called with an empty array.

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 2, 3];
}

(async function () {
  const q = await itiririAsync(generator())
    .groupJoin([1, 2, 3, 1, 1, 2], x => x, x => x, (x, y) => ({ x, y }))
    .awaitAll();
  q.toArray();
})();
//[ { x: 1, y: [ 1, 1, 1 ] },
//  { x: 2, y: [ 2, 2 ] },
//  { x: 3, y: [ 3 ] } ]

groupJoin is a deferred method and is executed only when the result sequence is iterated.

includes

Determines whether the sequence includes a certain element.

Syntax

includes(element: T): Promise<boolean>;
includes(element: T, fromIndex: number): Promise<boolean>;

Parameters

includes uses triple equals === to compare elements.

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 2, 3];
}

(async function () {
  await itiririAsync(generator()).includes(2); // returns: true
  await itiririAsync(generator()).includes(4); // returns: false
})();

indexOf

Returns the first (zero-based) index at which a given element can be found.

Syntax

indexOf(element: T): Promise<number>;
indexOf(element: T, fromIndex: number): Promise<number>;

Parameters

When an element is not found, returns -1.
indexOf uses triple equals === to compare elements.

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 2, 3];
}

(async function () {
  await itiririAsync(generator()).indexOf(2); // returns: 1
  await itiririAsync(generator()).indexOf(4); // returns: -1
})();

intersect

Returns a set intersection with a given sequence.

Syntax

intersect(others: Iterable<T>): AsyncIterableQuery<T>;
intersect<S>(other: Iterable<T>, selector: (element: T) => S): AsyncIterableQuery<T>;

Parameters

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 2, 3];
}

(async function () {
  const q = await itiririAsync(generator())
    .intersect([1, 2, 4])
    .awaitAll();
  q.toArray(); // returns: [1, 2]
})();

intersect is a deferred method and is executed only when the result sequence is iterated.

join

Returns a sequence of correlated elements transformation that match a given key.

Syntax

join<TKey, TRight, TResult>(
    other: Iterable<TRight>,
    leftKeySelector: (element: T, index: number) => TKey,
    rightKeySelector: (element: TRight, index: number) => TKey,
    joinSelector: (left: T, right: TRight) => TResult,
  ): AsyncIterableQuery<TResult>;

Parameters

The join method works as an sql inner join.

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 2, 3];
}

(async function () {
  const q = await itiririAsync(generator())
    .join([1, 1, 2], x => x, x => x, (x, y) => ({ x, y }))
    .awaitAll();
  q.toArray(); // returns: [ { x: 1, y: 1 }, { x: 1, y: 1 }, { x: 2, y: 2 } ]
})();

join is a deferred method and is executed only when the result sequence is iterated.

keys

Returns a sequence of keys for each index in the source sequence.

Syntax

keys(): AsyncIterableQuery<number>;

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* ['a', 'b', 'c'];
}

(async function () {
  const q = await itiririAsync(generator()).keys().awaitAll();
  q.toArray(); // returns: [0, 1, 2]
})();

keys is a deferred method and is executed only when the result sequence is iterated.

last

Returns the last element in a sequence.

Syntax

last(): Promise<T>;

For an empty sequence returns undefined.

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 2, 3, -2];
}

(async function () {
  await itiririAsync(generator()).last(); // returns: -2
})();

lastIndexOf

Returns the last index at which a given element can be found.

Syntax

lastIndexOf(element: T): Promise<number>;
lastIndexOf(element: T, fromIndex: number): Promise<number>;

Parameters

When an element is not found, returns -1.
lastIndexOf uses triple equals === to compare elements.

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 2, 3, 2, 1];
}

(async function () {
  await itiririAsync(generator()).lastIndexOf(2); // returns: 3
})();

leftJoin

Returns a sequence of correlated elements transformation that match a given key.

Syntax

leftJoin<TKey, TRight, TResult>(
    other: Iterable<TRight>,
    leftKeySelector: (element: T, index: number) => TKey,
    rightKeySelector: (element: TRight, index: number) => TKey,
    joinSelector: (left: T, right?: TRight) => TResult,
  ): AsyncIterableQuery<TResult>;

Parameters

The leftJoin method works as an sql left join. When an element from the left sequence doesn’t match with any of the elements from the right sequence, the joinSelector function is called with an undefined right value.

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 2, 3];
}

(async function () {
  const q = await itiririAsync(generator())
    .leftJoin([2, 3, 4, 2], n => n, n => n, (a, b) => `${a}-${b || '#'}`)
    .awaitAll();
  q.toArray(); // returns ['1-#', '2-2', '2-2', '3-3']
})();

leftJoin is a deferred method and is executed only when the result sequence is iterated.

length

Returns the number of elements in a sequence.

Syntax

length(): Promise<number>;
length(predicate: (element: T, index: number) => boolean): Promise<number>;

Parameters

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 2, 3];
}

(async function () {
  await itiririAsync(generator()).length(); // returns 3
})();

map

Returns a sequence of transformed values.

Syntax

map<S>(selector: (element: T, index: number) => S): AsyncIterableQuery<S>;

Parameters

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 2, 3];
}

function x10(numbers: AsyncIterable<number>) {
  return itiririAsync(numbers).map(n => n * 10);
}

(async function(){
  const numbers = await x10(generator()).awaitAll();
  console.log(numbers); // [10, 20, 30]
})();

map is a deferred method and is executed only when the result sequence is iterated.

max

Returns the maximum element in a sequence.

Syntax

max(): Promise<T>;
max(compareFn: (a: T, b: T) => number): Promise<T>;

Parameters

If sequence is empty, returns undefined.

Example

async function* generator1() {
  yield* [1, 42, 3];
}

async function* generator2() {
  yield* [];
}


(async function () {
  await itiririAsync(generator1()).max(); // returns 42
  await itiririAsync(generator2()).max(); // returns undefined
})();

min

Returns the minimum element in a sequence.

Syntax

min(): Promise<T>;
min(compareFn: (a: T, b: T) => number): Promise<T>;

Parameters

If sequence is empty, returns undefined.

Example

import itiririAsync from 'itiriri-async';

async function* generator1() {
  yield* [1, -2, 3];
}

async function* generator2() {
  yield* [];
}

(async function () {
  await itiririAsync(generator1()).min(); // returns -1
  await itiririAsync(generator2()).min(); // returns undefined
})();

nth

Returns the element at a specified index.

Syntax

nth(index: number): Promise<T>;

Parameters

If index is out of the range, returns undefined .

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, -2, 3];
}

(async function () {
  await itiririAsync(generator()).nth(2); // returns: 3
  await itiririAsync(generator()).nth(3); // returns: undefined
})();

prepend

Returns a sequence with given elements at the beginning.

Syntax

prepend(other: T): AsyncIterableQuery<T>;
prepend(other: Promise<T>): AsyncIterableQuery<T>;
prepend(other: Iterable<T>): AsyncIterableQuery<T>;
prepend(other: AsyncIterable<T>): AsyncIterableQuery<T>;

Parameters

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, -2, 3];
}

(async function () {
  const q = await itiririAsync(generator()).prepend(4).awaitAll();
  q.toArray(); // returns: [4, 1, -2, 3]
})();

(async function () {
  const q = await itiririAsync(generator()).prepend([0, 4]).awaitAll();
  q.toArray(); // returns: [0, 4, 1, -2, 3]
})();

prepend is a deferred method and is executed only when the result sequence is iterated.

reduce

Applies a function against an accumulator and each element (from left to right) to reduce it to a single value.

Syntax

reduce(
    callback: (accumulator: T, current: T, index: number) => T,
  ): Promise<T>;

reduce<S>(
    callback: (accumulator: S, current: T, index: number) => S,
    initialValue: S,
  ): Promise<S>;

Parameters

Calling reduce on an empty sequence without an initial value throws an error.

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 2, 3];
}

(async function () {
  // 5 + 10 + 20 + 30
  await itiririAsync(generator()).reduce((accum, elem) => accum + elem * 10, 5); // returns 65
})();

skip

Skips the specified number of elements from the beginning of sequence and returns the remaining ones.

Syntax

skip(count: number): AsyncIterableQuery<T>;

Parameters

When count is greater than actual number of elements, results in an empty sequence.

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 2, 3];
}

(async function () {
  const q = await itiririAsync(generator()).skip(1).awaitAll();
  q.toArray(); // returns: [2, 3]
})();

(async function () {
  const q = await itiririAsync(generator()).skip(10).awaitAll();
  q.toArray(); // returns: []
})();

skip is a deferred method and is executed only when the result sequence is iterated.

slice

Returns a sequence that represents the range of elements from start to end.

Syntax

slice(start: number, end: number): AsyncIterableQuery<T>;

Parameters

The end index is not included in the result.

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 2, 3, 3, 4];
}

(async function () {
  const q = await itiririAsync(generator()).slice(2, 4).awaitAll();
  q.toArray(); // returns: [3, 3]
})();

slice is a deferred method and is executed only when the result sequence is iterated.

some

Tests whether at least one element passes the predicate.

Syntax

some(predicate: (element: T, index: number) => boolean): Promise<boolean>;

Parameters

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 2, 3, -3, 4, 0];
}

(async function () {
  await itiririAsync(generator()).some(x => x < 0); // returns: true
  await itiririAsync(generator()).some(x => x > 5); // returns: false
})();

sum

Returns the sum of all elements.

Syntax

sum(): number;
sum(selector: (element: T, index: number) => number): Promise<number>;

Parameters

Optionally, a function can be provided to apply a transformation and map each element to a value.

Example

import itiririAsync from 'itiriri-async';

async function* generator1() {
  yield* [1, 2, 3];
}

async function* generator2() {
  yield* [{ val: 3 }, { val: 5 }];
}

(async function () {
  await itiririAsync(generator1()).sum(); // returns: 6
  await itiririAsync(generator2()).sum(x => x.val); // returns: 8
})();

take

Returns a specified number of elements from the beginning of sequence.

Syntax

take(count: number): AsyncIterableQuery<T>;

Parameters

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 2, 3];
}

(async function () {
  const q = await itiririAsync(generator()).take(2).awaitAll();
  q.toArray(); // returns: [1, 2]
})();

(async function () {
  const q = await itiririAsync(generator()).take(0).awaitAll();
  q.toArray(); // returns: []
})();

take is a deferred method and is executed only when the result sequence is iterated.

union

Returns a set union with a given sequence.

Syntax

union(other: AsyncIterable<T>): AsyncIterableQuery<T>;
union<S>(other: AsyncIterable<T>, selector: (element: T) => S): AsyncIterableQuery<T>;

Parameters

Example

import itiririAsync from 'itiriri-async';

async function* generator1() {
  yield* [1, 2, 3];
}

async function* generator2() {
  yield* [3, 4, 5];
}

(async function () {
  const q = await itiririAsync(generator1()).union(generator2()).awaitAll();
  q.toArray(); // returns [1, 2, 3, 4, 5]
})();

union is a deferred method and is executed only when the result sequence is iterated.

values

Returns a sequence of values for each index in the source sequence.

Syntax

values(): AsyncIterableQuery<T>;

Example

import itiririAsync from 'itiriri-async';

async function* generator() {
  yield* [1, 0, 2, 3];
}

(async function () {
  const q = await itiririAsync(generator()).values().awaitAll();
  q.toArray(); // [1, 0, 2, 3]
})();

values is a deferred method and is executed only when the result sequence is iterated.

License

MIT