Closed dead-claudia closed 3 years ago
It would be nice if filter
indeed were not generator based & could stream results.
That said, I think your example is doable by hacking around the problem somewhat, and having asyncMap synchronously return the promise rather than await it to be resolved, & awaiting/filtering latter:
AsyncIterator.from(glob("src/**/*.js"))
.asyncMap(file => fs.readFile(file))
.parallel(1000) // perhaps parallel could do the resolving, which would simplify code below
.filter(async (file) => (await file).includes("whatever"))
.take(1)
.toArray() // the file promise, unless we add another step to resolve
This idea of having asyncMap synchronously return the promise
may need to be even uglier in some cases, to avoid the synchronization async generators introduce. If the above doesn't work, it might have to become:
AsyncIterator.from(glob("src/**/*.js"))
.asyncMap(file => ({promise: fs.readFile(file)}))
.parallel(1000)
.filter(file => (await file.promise).includes("whatever"))
.take(1)
.toArray()
Gross. That would be unfortunate.
this is definitely out of scope for this proposal (i wouldn't be against this kind of functionality existing in the language though)
@devsnek is there a reason we want to base this proposal on generators? it feels like it was convenience rather than cause. i don't see that a re-implementation off generators would be challenging.
it would be very nice to not have these iteration helpers be so constrained.
the problem this issue is discussing is out of scope. the implementation of the methods in this proposal have nothing to do with that.
i don't understand your assertion that the the problem is out of scope. how so? iteration-helpers describes itself as:
A proposal for several interfaces that will help with general usage and consumption of iterators in ECMAScript.
surely we want to do a good job making sure these iteration helpers work in asynchronous use cases? why would we exclude asynchronous operations from iteration-helpers functioning?
edit: as i think this over some, i am becoming somewhat sympathetic to this being chalked up as an async-iteration issue, not a helpers issue. my second psuedocode example, of creating {promise}
objects to by-pass the async-iteration limitations, is a reasonable demonstration of async-iteration's limitations.
trying to work with the constraints we have, perhaps we need to move parallelization out of the middle of the pipeline:
AsyncIterator.from(glob("src/**/*.js"))
.parallelRaceMap(file => fs.readFile(file), 1000)
.filter(file => file.includes("whatever"))
.take(1)
.toArray()
As the one starting the original conversation I'd like to add that .parallel
was just a "first idea", and although I still like how it would hypothetically chain, it pretty much collides with the spec (including this proposal). Yielding a Promise inside an async generator also already awaits the Promise, so I'd say doing the same in .map
and .filter
is reasonable (and the opposite would be very confusing). Thus I agree to @devsnek that this is "not an issue" for this proposal.
That said there are still plenty of options to introduce parallel processing into iterators, e.g. a parallelMap
which I guess can be discussed in a followup proposal (or the one already drafted by @isiahmeadows ).
This came up in someone proposing an alternate formulation of my promise scheduling proposal. (H/T @Jonasdoubleyou for the suggestion that would require this)
Async generators enforce synchrony:
However, some cases, like stateless
.map
and.filter
transforms, could work with an async iterator that allows being read concurrently, and the spec doesn't exactly write that out as a possibility - it's just a natural part of the contract with how async iterables are enumerated.The hypothetical operator here is
AsyncIterator.prototype.parallel
, and it would allow controlled parallel iteration of the async iterable, and this would come in handy with things like enumerating files in a glob stream, breaking once one of them reads a file. Think of it like this pseudocode:I'm personally neutral-negative on the idea, but I can see the value of doing it this way, and I feel that it should be addressed whether you all want to leave the door open to this or not.