Iterable.flow
At the moment of writing flow does not have a proper support for Iterable/Iterator/Generator, it does not allow [Symbol.iterator] in class definitions and insteard requires use of @@iterator which on the other hand breaks babel.
This libary provides a workaround in form of Iterable.Sync / Iterable.Async
classes that do have [Symbol.iterator] / [Symbol.asyncIterator] method
which delegate to iterator / asyncIterator allowing you to define valid iterators that both flow and babel understand and that also works natively in JS engines with Symbol.iterator / Symbol.asyncIterator support in them.
Usage
Import
Rest of the the document & provided code examples assumes that library is installed (with yarn or npm) and imported as follows:
import Iterable from "iterable.flow"Sync Iterator
In order to define sync iterator you'd neet to implement next method and iterator method that most likely returns this.
class RangeIterator extends Iterable.Sync<number> {
value:number
max:number
static new(from:number=0, to:number=Infinity)
constructor(from:number, to:number) {
super()
this.value = from
this.max = to
}
iterator() {
return this
}
next() {
const {value, max} = this
if (value <= max) {
this.value ++
return {done:false, value}
} else {
return {done:true}
}
}
}
console.log([...Range.new(0, 3)]) //=> [0, 1, 2, 3]Sync Iterable
In order to define sync iteratable you just need to implemnet iterator method:
class Range extends Iterable.Sync<number> {
from:number
to:number
constructor(from:number, to:number) {
super()
this.from = from
this.to = to
}
static new(from:number=0, to:number=Infinity) {
return new Range(from, to)
}
*iterator():Iterable.Iterator<number> {
let n = this.from
while (n <= this.to) {
yield n++
}
}
}
console.log([...Range.new(0, 4)]) // [0, 1, 2, 3, 4]Note: You can also return manually defined Iterator (as illustrated in previous example) from iterator method.
Async Iterable
class Beat extends Iterable.Async<number> {
tempo:number
time:number
static new(tempo:number, time:number = 0) {
this.tempo = tempo
this.time = time
}
constructor(tempo:number, time:number) {
super()
this.tempo = tempo
this.time = time
}
asyncIterator() {
return this
}
next() {
return new Promise(resolve => {
setTimeout(() => {
resolve({ done:false, value: (this.time += this.tempo) })
}, this.tempo)
})
}
}
async function main() {
for await (let time of Beat.new(100)) {
// ...
}
}Install
npm install iterable.flow