Giter Site home page Giter Site logo

miguelcastillo / coseq Goto Github PK

View Code? Open in Web Editor NEW
14.0 3.0 2.0 36 KB

high order functions for JavaScript async/sync iterators

License: MIT License

JavaScript 100.00%
asynchronous yield coroutines iterator chain javascript promise async-iterators sequence

coseq's Introduction

coseq

Build StatusGreenkeeper badge

Compose chains of functions to manipulate data via synchronous and asynchronous iterators. Data iteration is lazy, which means that items are not read/evaluated until the data is needed. This allows for a really nice integration with infinite and/or really large data sets where eager evaluation and itermediate data storage is prohibitively expensive or impossible.

async iterators are a thing in JavaScript.

The first use case is around generators, which can create asynchronous and synchrnous iterators. You can craft generators to yield anything you want (more than once), in which case they are referred to as coroutines. Combining the coroutine nature of generators and the ability to iterate over the data they yield is why the name coseq came about. Not very creative - I know.

subroutines return one value. coroutines can yield multiple values before running to completion.

You can take a look at this codepen if you want to play with coseq.

features

  • Lazy data evaluation
    • infinite data sequence
    • large data sets
  • No intermediate arrays
  • Asynchronous and synchronous iterators
    • Compatibility with for await (var x of iterator) and for (var x of iterator)

usage

install

$ npm install coseq --save

api

coseq

Method that wraps an iterator to create chains of high order functions to process your data.

The contract with coseq is the iterator protocol, which is why anything that can create an interator can be used with coseq. This includes array, Set, Map... etc.

Below is an example of filtering even numbers and multiplying the values by 2.

import coseq from 'coseq'

const set = new Set([1, 2, 3, 4]);

const sequence = coseq(set.values())
  .filter(value => value % 2)
  .map(value => value * 2);

for (var value of sequence) {
  console.log(value);
}

The potential of coseq can be more easily experienced with infinite or really large data sets. Generators are a good example of this.

function* getItemsSync() {
  for (var i = 1; i <= 5000000; i++) {
    yield i;
  }

  return "YES!!";
}

const sequence = coseq(getItemsSync())
  .skip(500)
  .filter(value => value % 2)
  .map(value => value * 2);

for (var value of sequence) {
  console.log(value);
}

Below is a contrived example with async generators.

async function* getItemsAsync() {
  for (var i = 1; i <= 5000000; i++) {
    yield await i;
  }

  return "YES!!";
}

const sequence = coseq(getItemsAsync())
  .filter(value => value % 2)
  .map(value => value * 2);

async function runSequence(sequence) {
  for await (var value of sequence) {
    console.log(value);
  }
}

runSequence(sequence);

You can also await values in the sequence with the helper method awaitValue.

async function* getItemsAsync() {
  for (var i = 1; i <= 5000000; i++) {
    yield await Promise.resolve(i); // <== This yields promises that can be awaited with awaitValue
  }

  return "YES!!";
}

const sequence = coseq(getItemsAsync())
  .awaitValue() // <== This will await the promise yielded by the iterator
  .filter(value => value % 2)
  .map(value => value * 2);
  
async function runSequence(sequence) {
  for await (var value of sequence) {
    console.log(value);
  }
}

runSequence(sequence);

filter

Method to skip items in a sequence when the provided predicate returns falsy values.

alias where

coseq(getItemsAsync()).filter(value => value % 2);

map

Method to transform the current value in the sequence.

alias select

coseq(getItemsAsync()).map(value => value * 2);

forEach

Method to iterate through the items in a sequence. You can use this instead of the for of and for await of constructs.

forEach runs asynchronously and returns a promise, which is particularly useful for accessing to the value returned by generator functions.

In the example below, all values are printed out in the forEach. And when the generator is all done generating values, the last then method in the chain will print YES!!;

async function* getItemsAsync() {
  for (var i = 1; i <= 5000000; i++) {
    yield await i;
  }

  return "YES!!";
}

coseq(getItemsAsync())
  .filter(value => value % 2)
  .map(value => value * 2)
  .forEach(value => console.log(result.value))
  .then(result => console.log(result.value));

take

Method to read a specific number of items from a sequence. This is a one time operation so once the specified number of items are read, no further values will be processed.

The example below will pull the first 3 items

coseq(getItemsAsync()).take(3);

takeUntil

Method to read items from a sequence until the predicate function returns true. This is a one time operation so once the condition is true, the sequence will no longer return values.

The example below will pull items until the value is equal to 2, including 2.

coseq(getItemsAsync()).takeUntil(value => value === 2);

takeWhile

Method to read items from a sequence while the predicate function returns true. This is a one time operation so once the condition is no longer satisfied, the sequence will no longer return values.

The example below will pull items while the value is smaller or equal to 2

coseq(getItemsAsync()).takeWhile(value => value <= 2);

skip

Method to skip (discard) a specific number of items in a sequence. This is a one time operation so once the specified number of items are read, no more items will be skipped.

The example below skips the first 3 items.

coseq(getItemsAsync()).skip(3);

skipUntil

Method to skip (discard) items until the provided predicate function returns true. This is a one time operation so once the condition is true, skipUntil will no longer skip items.

The example below skips until the value is 3.

coseq(getItemsAsync()).skipUntil(value => value === 3);

skipWhile

Method to skip (discard) items while the provided predicate function return true. This is a one time operation so once the condition is true, skipWhile will no longer skip items.

The example below skips while the value is 1.

coseq(getItemsAsync()).skipWhile(value => value === 1);

awaitValue (async sequence only)

Method to await the current value. The primary use case for this is when a sequence yields a promise which needs to be awaited.

coseq(getItemsAsync())
  .awaitValue()
  .skipUntil(value => value === 2);

delay (async sequence only)

Method to add a delay before continuing to process the current item in the sequence. The delay is sepecified in milliseconds.

coseq(getItemsAsync())
  .skipUntil(value => value === 2)
  .delay(3000);

coseq's People

Contributors

greenkeeper[bot] avatar miguelcastillo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

coseq's Issues

An in-range update of pakit is breaking the build 🚨

Version 0.3.3 of pakit just got published.

Branch Build failing 🚨
Dependency pakit
Current Version 0.3.2
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As pakit is β€œonly” a devDependency of this project it might not break production or downstream projects, but β€œonly” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this πŸ’ͺ


Status Details
  • ❌ continuous-integration/travis-ci/push The Travis CI build could not complete due to an error Details
Commits

The new version differs by 10 commits .

  • 3e16e95 Release v0.3.3
  • ec91f50 Merge pull request #31 from MiguelCastillo/eslint-config
  • 3bfb0e1 adding ability to configure eslint module
  • f236641 Merge pull request #30 from MiguelCastillo/greenkeeper/initial
  • 71511c5 Merge pull request #29 from MiguelCastillo/loader-plugins-cleanup
  • dae0b1a refactored the logic for loading up loader plugins to be a bit more streamlined.
  • d5c0b98 Merge pull request #28 from MiguelCastillo/readme-caching-line
  • 98792f8 adding small reference to caching
  • 54c572b docs(readme): add Greenkeeper badge
  • 46307d9 chore(package): update dependencies

See the full diff.

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

issue with iterators reading data out of the data source even after the iterator is flagged as done

The issue is seen when processing an iterator and applying a takeUntil action. If the iterator has more data in it after takeUntil is satisfied, further iterator.next calls would cause items to continue to be read causing other action sequences to get the wrong data from the iterator.

      function* getItemsAsync() {
        for (var i = 1; i <= 5; i++) {
          yield Promise.resolve(i);
        }

        return "YES!!";
      }

        asyncIterator = coseq(getItemsAsync())
          .takeUntil(value => value === 3)
          .asyncIterator();


      assertNextValue(1, false);
      assertNextValue(2, false);
      assertNextValue(3, false);
      assertNextValue(undefined, true);
      assertNextValue(undefined, true);

      // this right here fails because the iterator returns "YES!!"
      assertNextValue(undefined, true);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.