Skip to content
This repository has been archived by the owner on Oct 8, 2024. It is now read-only.

.async helper for getting an async iterator from a sync iterator #160

Closed
bakkot opened this issue Nov 3, 2021 · 3 comments · Fixed by #202
Closed

.async helper for getting an async iterator from a sync iterator #160

bakkot opened this issue Nov 3, 2021 · 3 comments · Fixed by #202

Comments

@bakkot
Copy link
Collaborator

bakkot commented Nov 3, 2021

I realize it's probably past the point where we want to add new methods, but I wanted to write this down here so we will at least have discussed it, and maybe pick it up in a later proposal. (Sidebar: time for a future proposal label, maybe?)

In some code I was writing today, I had an array I wanted to filter and then flatMap. The problem was that the mapper function was async (i.e., it returned a promise of an array), so I couldn't use Array.prototype.flatMap (which requires the mapper to return an array). What I first wrote was

(await Promise.all(array.filter(fn).map(mapper)).flat()

but then I realized I really wanted to do the async operations in sequence, not in parallel. There's no good way to do that without a manual for await loop right now - which is frustrating, since this really is most clearly expressed as a filter followed by a flatMap.

With this proposal in its current state, I could instead write

await AsyncIterator.from(array.values().filter(fn)).flatMap(mapper).toArray()

which is better than a for await, but still kind of awkward because of the weird AsyncIterator.from in the middle (or rather not in the middle; you have to read carefully to see the point at which it applies). So it seems like it might be useful to have an async method on the sync iterator prototype which did the wrapping for you, such that you could do

await array.values().filter(fn).async().flatMap(mapper).toArray()

Obviously there's a bunch of other ways to write this, especially if we get some form of pipeline. But this does feel like it's a primitive operation on sync iterators, and so might belong on Iterator.prototype.


Edit a few months later: I needed this again in a simpler case. I wanted to do a filter, but my filtering function was async. It would have been nice to do await arr.values().toAsync().filter(x => await foo(x)).toArray(). This is probably a more obvious example than flatMap.

@zloirock
Copy link
Contributor

zloirock commented Nov 3, 2021

It's like .toArray() vs Array.from case. Makes sense. (However, rather I'm a fan of #36 and .to(AsyncIterator)).

@Jack-Works
Copy link
Member

I realize it's probably past the point where we want to add new methods

I don't think so. I think this helper is useful, let's add this function since we have toArray. toAsync is a good name IMO.

@codehag
Copy link
Collaborator

codehag commented Dec 2, 2021

toAsync sounds good. will add it in the next round

zloirock added a commit to zloirock/core-js that referenced this issue Dec 3, 2021
zloirock added a commit to zloirock/core-js that referenced this issue Dec 9, 2021
@michaelficarra michaelficarra added the good follow-on proposal this would be good but doesn't need to be in the first milestone label Jul 5, 2022
@bakkot bakkot removed the good follow-on proposal this would be good but doesn't need to be in the first milestone label Jun 3, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants