Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using IxJS with Node #227

Open
acchou opened this issue Apr 17, 2018 · 4 comments
Open

Using IxJS with Node #227

acchou opened this issue Apr 17, 2018 · 4 comments

Comments

@acchou
Copy link

acchou commented Apr 17, 2018

IxJS version:
v2.3.5

Code to reproduce:

tsconfig.json:

{
    "compilerOptions": {
        "outDir": "build",
        "module": "commonjs",
        "target": "es6",
        "lib": ["esnext", "dom", "esnext.asynciterable"]
    }
}

package.json:

{
    "name": "ixproj",
    "version": "1.0.0",
    "description": "example project for ixjs",
    "main": "main.js",
    "scripts": {
        "build": "tsc"
    },
    "author": "",
    "license": "ISC",
    "engines": {
        "node": ">=8.0.0"
    },
    "dependencies": {
        "ix": "^2.3.5"
    },
    "devDependencies": {
        "@types/node": "^8.5.1",
        "typescript": "^2.6.2"
    }
}

src/main.js:

//(<any>Symbol).asyncIterator = Symbol.asyncIterator || Symbol.for("Symbol.asyncIterator");

import { AsyncIterable } from "ix";

async function* gen() {
    yield 1;
    yield 2;
    yield 3;
    yield 4;
}

AsyncIterable.from(gen())
    .filter(x => x % 2 === 0)
    .map(x => x * 2)
    .forEach(x => console.log(`Next ${x}`))
    .catch(err => console.log(`Error ${err}`));

Expected behavior:

This is pretty much the example in the readme, the expected output is:

Next 4
Next 8

Actual behavior:

ixproj/build/main.js:5
    if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
                               ^

TypeError: Symbol.asyncIterator is not defined.

Additional information:

First of all, thanks for building IxJS, it seems like a very powerful and compact library for working with async iterators/generators. The natural way backpressure is handled in this framework seems to make IxJS a good fit for backend programming with Node.js. But there are a few issues I ran into when trying out very simple examples, that might prevent others from getting to know IxJS in a Node.js setup.

There are a few things here:

  • IxJS requires the dom library to compile. Removing "lib": ["dom"] from tsconfig.json gives the following errors:
$ tsc
node_modules/ix/asynciterable/fromevent.ts(17,29): error TS2304: Cannot find name 'EventTarget'.
node_modules/ix/asynciterable/fromevent.ts(23,42): error TS2304: Cannot find name 'EventTarget'.
node_modules/ix/asynciterable/fromevent.ts(37,21): error TS2304: Cannot find name 'EventTarget'.
node_modules/ix/asynciterable/fromevent.ts(39,43): error TS2304: Cannot find name 'EventListener'.
node_modules/ix/asynciterable/fromevent.ts(40,46): error TS2304: Cannot find name 'EventListener'.

This can be addressed by users adding their own ix.d.ts with some type definitions to make the compiler happy, but perhaps these could be added to IxJS itself. The types seem harmless to add because TypeScript will do declaration merging with the dom library, and there is a dynamic check in fromevent.ts:

function isEventTarget(obj: any): obj is EventTarget {
  return (
    !!obj &&
    typeof obj.addEventListener === 'function' &&
    typeof obj.removeEventListener === 'function'
  );
}
  • Symbol.asyncIterator isn't defined when using Node, uncommenting the first line allows the example to run correctly:
(<any>Symbol).asyncIterator = Symbol.asyncIterator || Symbol.for("Symbol.asyncIterator");

But this isn't mentioned anywhere. In particular, this definition must be before importing IxJS, otherwise the example yields an infinite loop:

Next undefined
Next undefined
Next undefined
Next undefined
Next undefined
Next undefined
Next undefined
Next undefined
Next undefined
Next undefined
...

Also, out of curiosity I tried to decipher how IxJS's tests run without defining Symbol.asyncIterator somewhere and I couldn't figure it out. It might be helpful to document here for anyone who is curious later.

@acchou
Copy link
Author

acchou commented Apr 17, 2018

Here's a repo with the project: https://github.com/acchou/ixjs-example

@trxcllnt
Copy link
Member

@acchou to use Ix without transpiling, you need to launch with node's --harmony_async_iteration flag

@trxcllnt
Copy link
Member

The tests are run via ts-node, which I believe polyfills any native JS globals based on the tsconfig settings it's run with. It's probably still a good idea to pull in a polyfill for Symbol.asyncIterator though.

@acchou
Copy link
Author

acchou commented Apr 17, 2018

Thank you, this resolves the issue with Symbol.asyncIterator... I wasn't aware of this flag as I'm new to Node and to generators.

How about the DOM library issue? I can issue a PR with some type definitions for EventTarget and EventListener if that is a way forward.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants