create-async-generator

2.0.0 • Public • Published

create-async-generator

Create an async generator out of any value and pipe async generators into each other.

Installation

npm i create-async-generator

from

From will convert any value into an async generator.

from using promise

Passing a promise converts it into an async generator that will yield the promise result

import { from } from 'create-async-generator';

const input = Promise.resolve(1);
const generator = from(input);

for await (const output of generator()) {
  console.log(output); //=> 1
}

from using AsyncIterable

Passing an async iterable will yield all of its values

import { from } from 'create-async-generator';

async function* inputGenerator(value) {
  yield value * 2;
  yield value * 3;
  yield value * 4;
}

const input = inputGenerator(2);

const generator = from(input);

for await (const output of generator()) {
  console.log(output); //=> 4, 6, 8
}

from using function

Functions will be called with the generator arguments

import { from } from 'create-async-generator';

async inputGenerator(value) {
  // value will be the generator argument
  return value * 2;
}

const generator = from(inputGenerator);

for await (const output of generator(2)) {
  console.log(output); //=> 4
}

from using generator function

Generator functions will be called with the generator arguments

import { from } from 'create-async-generator';

async function* inputGenerator(value) {
  // value will be the generator argument
  yield value * 2;
  yield value * 3;
  yield value * 4;
}

const generator = from(inputGenerator);

for await (const output of generator(2)) {
  console.log(output); //=> 4, 6, 8
}

from using a value that is non of the above

Any argument that is not a function, promise or async iterable will return a generator that will yield the passed argument.

import { from } from 'create-async-generator';

const input = 1;
const generator = from(input);

for await (const output of generator()) {
  console.log(output); //=> 1
}

combineIterable

combineIterable depends on the async-iterators-combine package. Every item in the passed iterable will be converted to an async generator (using from) and yielded values will be combined into iterables. For a list of all options see the async-iterators-combine docs

import { combineIterable } from 'create-async-generator';

const generator = combineIterable([
  async function* (value) {
    yield value * 2;
    yield value * 3;
    yield value * 4;
  },
  (value) => Promise.resolve(value * 10),
  Promise.resolve('wow'),
  'example',
]);

for await (const output of generator(2)) {
  console.log(output); //=> [4, 20, 'wow', 'example'], [6, 20, 'wow', 'example'], [8, 20, 'wow', 'example']
}

combineObject

combineObject behaves exactly the same as combineIterable but accepts an object instead of an iterable and will yield objects.

import { combineObject } from 'create-async-generator';

const generator = combineObject({
  a: async function* (value) {
    yield value * 2;
    yield value * 3;
    yield value * 4;
  },
  b: (value) => Promise.resolve(value * 10),
  c: Promise.resolve('wow'),
  d: 'example',
});

for await (const output of generator(2)) {
  console.log(output); //=> { a: 4, b: 20, c: 'wow', d: 'example' }, { a: 6, b: 20, c: 'wow', d: 'example' }, { a: 8, b: 20, c: 'wow', d: 'example' }
}

YieldableAsyncGenerator

new YieldableAsyncGenerator() creates an object that conforms to the async iterable and async iterator protocol and includes a yield method to yield values. When a signal is passed to the constructor (new YieldableAsyncGenerator({ signal })) the generator will be returned as soon as the signal is aborted.

import { YieldableAsyncGenerator } from 'create-async-generator';

const generator = new YieldableAsyncGenerator();

await Promise.all([
  (async () => {
    for await (const output of generator) {
      console.log(output) //=> 1, 2, 3
    }
  })(),
  (async () => {
    await new Promise((resolve) => setTimeout(resolve, 100));
    generator.yield(1);
    await new Promise((resolve) => setTimeout(resolve, 100));
    generator.yield(2);
    await new Promise((resolve) => setTimeout(resolve, 100));
    generator.yield(3);
  })(),
])

ShareableAsyncGenerator

Extends YieldableAsyncGenerator and adds a share method that will return a new object that conforms to the async iterable and async iterator protocol that will yield all values from the parent object but can be returned and thrown independently. The share method also takes an object with a signal as parameter (share({ signal })) that will return the generator as soon as the signal is aborted.

import { ShareableAsyncGenerator } from 'create-async-generator';

const generator = new ShareableAsyncGenerator();

await Promise.all([
  (async () => {
    for await (const output of generator.share()) {
      console.log(output) //=> 1, 2
      if (output === 2) {
        return;
      }
    }
  })(),
  (async () => {
    for await (const output of generator.share()) {
      console.log(output) //=> 1, 2, 3
    }
  })(),
  (async () => {
    for await (const output of generator.share()) {
      console.log(output) //=> 1
      if (output === 1) {
        return;
      }
    }
  })(),
  (async () => {
    await new Promise((resolve) => setTimeout(resolve, 100));
    generator.yield(1);
    await new Promise((resolve) => setTimeout(resolve, 100));
    generator.yield(2);
    await new Promise((resolve) => setTimeout(resolve, 100));
    generator.yield(3);
  })(),
])

## pipe

Will pipe the result of the first function as first argument in the following function, any arguments passed into the resulting function will be passed into the first function and as additional arguments into succeeding functions.

```js
import { pipe } from 'create-async-generator';

const generator = pipe(
  async function* (value) {
    yield value * 2;
    yield value * 3;
    yield value * 4;
  },
  async function* (generator, value) {
    for await (const output of generator) {
      yield output * 1 + value;
      yield output * 2 + value;
      yield output * 3 + value;
    }
  }
)

for await (const output of generator(2)) {
  console.log(output); //=> 6, 10, 14, 8, 14, 20, 10, 18, 26
}

Operators

Operators return generator functions that can be used as arguments when calling pipe.

map

Map every yielded value to the value returned by the mapping method.

import { pipe, map } from 'create-async-generator';

async function* inputGenerator(value) {
  yield value * 2;
  yield value * 3;
  yield value * 4;
}

const generator = pipe(
  inputGenerator,
  map((value, i, originalValue) => value / 2 * i + originalValue),
);

for await (const output of generator(2)) {
  console.log(output); //=> 2, 5, 10 
}

filter

Will skip the yield if the value returned by the mapping method is falsy.

import { pipe, filter } from 'create-async-generator';

async function* inputGenerator() {
  yield 2;
  yield 3;
  yield 4;
  yield 5;
  yield 6;
}

const generator = pipe(
  inputGenerator,
  filter((value, i, _originalValue) => value % 2 === 0),
);

for await (const output of generator()) {
  console.log(output); //=> 2, 4, 6 
}

delegateMap

Delegates the async iterable to the generator function that is returned from the map method.

import { pipe, delegateMap } from 'create-async-generator';

async function* inputGenerator(value) {
  yield value * 2;
  yield value * 3;
  yield value * 4;
}

const generator = pipe(
  inputGenerator,
  delegateMap((value, i, _originalValue) => value % 2 === 0
    ? async function* (originalValue) {
      yield originalValue * 2;
      yield originalValue * 3;
      yield originalValue * 4;
    } : async function* (originalValue) {
      yield originalValue * 20;
      yield originalValue * 30;
      yield originalValue * 40;
    }
  )
);

for await (const output of generator(2)) {
  console.log(output); //=> 4, 6, 8, 60, 90, 120, 8, 12, 16, 100, 150, 200, 12, 18, 24
}

raceMap

Uses Promise.race to race the next yield and the map function, skips the map output and aborts the passed in AbortSignal if the next yield wins.

import { pipe, raceMap } from 'create-async-generator';

async function* inputGenerator(value) {
  yield value * 2;
  await new promise((resolve) => settimeout(resolve, 100));
  yield value * 3;
  await new promise((resolve) => settimeout(resolve, 50));
  yield value * 4;
}

const generator = pipe(
  inputGenerator,
  raceMap((value, i, _abortSignal, _originalValue) => {
    await new promise((resolve) => settimeout(resolve, 60));
    yield value * 10;
  })
);

for await (const output of generator(2)) {
  console.log(output); //=> 40, 80
}

Package Sidebar

Install

npm i create-async-generator

Weekly Downloads

4

Version

2.0.0

License

MIT

Unpacked Size

62.1 kB

Total Files

32

Last publish

Collaborators

  • handijk