Giter Site home page Giter Site logo

bdchauvette / icw Goto Github PK

View Code? Open in Web Editor NEW
1.0 3.0 0.0 474 KB

:boat: Async iteration utility library for JavaScript

License: BSD Zero Clause License

JavaScript 80.35% TypeScript 14.79% HTML 4.86%
async-iterators javascript iterable async stream-api

icw's People

Contributors

bdchauvette avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar

icw's Issues

Create browser builds

TODO:

  • Create bundled browser build
  • Create mini bundles for each top-level file in src

This is a bundling-only step for better interop with unpkg, and should not involve transpiling or polyfills.

Add `isEqual`

For comparing whether the items in each iterable are Object.is equal

isEqual([1, 2, 3], [1, 2, 3]) // true
isEqual([1, 2, 3], [4, 5, 6]) // false

Support random access for Array-like inputs

For functions like nth, indexOf and last, it would be nice to have a fast path that just accesses the value at the underlying index (if available), instead of iterating through the entire iterable.

Allow functions to accept any IterableLike input

Proposal

Instead of only accepting AsyncIterable<T> and Iterable<T>, functions should accept a type of:

type IterableLike<T> = AsyncIterable<T> | Iterable<T> | ArrayLike<T> | Promise<T> | PromiseLike<T>

How this helps

This accomplishes two things:

Brings the acceptable input in line with things that can be converted using from

Regarding #1, from currently accepts a range of inputs that are converted to an AsyncIterable. If we implicitly accept these inputs in each method, then

We can accomplish this without too much overhead by adding an (internal?) method that avoids casting AsyncIterable and Iterable to an AsyncIterable, e.g.

function toIterable(iterableLike: IterableLike<T>) {
  if (isAsyncIterable(iterableLike) || isIterable(iterableLike)) return iterableLike;
  // ...
}

Then inside each function, instead of just doing:

for await (let value of iterable) {}

we can do

for await (let value of toIterable(iterable)) {}

This doesn't replace from, which converts its input to an AsyncIterable, but it does make the overall API more (IMO) intuitive.

(Partially) solves the problem of what to do about methods that only return single values

When trying to implement methods that return single values (e.g. reduce, indexOf, etc), there's a bit of tension between wanting to make an API that's super chainable and one that behaves more like native JS.

Currently, these methods return AsyncIterables that contain a single item. This lets us pass the result of these items into any of the other functions that expect an iterable, e.g.

// Weird, but illustrative?
compose(
  _ => map(_, double),
  _ => reduce(_, sum),
  _ => map(_, (n => [n, n, n]),
  _ => reduce(_, sum),
)

However, this is less intuitive if we really just want a single value:

// Doesn't work :(
let summedValues = await reduce([1, 2, 3], sum)

If we make reduce & friends return a Promise, and make all of the functions accept an IterableLike, we get the best of both worlds.

Problems

Mixes eager and lazy evaluation

This makes it harder to know which methods will be eager, and which will be lazy, which adds overall complexity to the library.

We could fix this by making everything eager, but that's even less appealing to me.

We could also have a rule like "any method that returns a single value returns a Promise instead of an iterable", but I'm not sure if that's ideal, either?

Complicates the chainable API

Returning Promises from chainable methods (e.g. ICW.of(1, 2, 3).reduce(sum)) breaks the chainability, and leads to a disconnect between the standalone methods and the chainable interface. That is, it's kind of weird if we can compose or flow all of the standalone methods together, but we can't do that with the chainable ones.

To be fair, the chainable API (i.e. the ICW class) is kind of a second-class citizen because it's not tree-shakeable, and is more complex to implement than the standalone functions.

We could also get around this by having the chainable methods return a subclass of Promise that contains all of the chainable methods, e.g.

class ICW<T> {
  // ...
  reduce(fn): ICWPromise<T> {}
}

But I'm not sure (1) how to do that without circular dependencies, and (2) if it's worth the complexity.

It might be better to just punt on making these particular methods chainable for now.

Upgrade to babel 7

TODO:

  • Upgrade to babel 7
  • Replace tsc with @babel/preset-typescript
  • Only use tsc for emitting declarations

This will hopefully simplify the testing setup, and will allow us to use babel plugins to e.g. add file extensions to import statements, so the script can work in the browser.

Add `ICWNode` class

i.e. a chainable class that extends ICW, but also includes Node-only methods for Streams or whatever.

Should probably use Symbol.species somehow.

cf. #21

Add `sort`

This will be kind of gross, because it will require buffering all of the values before sorting them ๐Ÿ˜ฟ

Add `toCallback`

To convert to a node style callback, e.g.

ICW
  .from([1, 2, 3])
  .map(double)
  .toCallback((err, result) => console.log(result));

// 2
// 4
// 6

Add `range`

i.e. a function that creates an iterable containing numbers in the range provided by the arguments:

for await (let n of range(0, 3)) {
  console.log(n)
} 

// 0
// 1
// 2
// 3

Not sure if this really needs to async, but might be good for consistency?

Add `ICWDOM` class

i.e. a chainable class that extends ICW, but also includes DOM-only methods.

Should probably use Symbol.species somehow.

cf. #22

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.