IxJS
IxJS copied to clipboard
Using IxJS with Node
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.
Here's a repo with the project: https://github.com/acchou/ixjs-example
@acchou to use Ix without transpiling, you need to launch with node's --harmony_async_iteration
flag
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.
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.