npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

create-async-generator

v2.0.0

Published

Create an async generator out of any value or combination of values and pipe async generators into each other

Downloads

9

Readme

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
}