Oh wow, this is next level! Also TIL about for-await-of; neat. Do you have some examples of where this can be really helpful in real world code? I'm wondering when I should think to maybe reach for this instead of cobbling something else together π Thanks!
Generally, the async iteration is well suited for all those circumstances where consumers should have control over the flow of data.
Next time I'll show some more concrete examples thanks to async generators, but for now a good starting point to satisfy your needs surely are Node.js Readable streams. WHATWG Streams are async iterables too.
A while back I also wrote a library to manipulate async stream with async iterables. You might find it interesting. It was in the context of this article.
It is a very nice serie you wrote here. However I think you should stress more on the fact that closing iterable is a leaky abstraction(by Reginald βRaganwaldβ Braithwaite). You did a bit in the second article but I think it deserves more attention. It is usually better to use built in consumers (such for await statement) to avoid problems
It could seem a stupid answer but I strongly believe in well-commented programs, so what is not immediately understandable should be highlighted with a proper comment/explanation.
I am with you, I think that custom implementations of interfaces like these should be kept to a minimum but...there is always an exception.
Like here: github.com/nodejs/node/blob/master...
One of the Node.js streams maintainer told me that an async gen would be too slow and hard to implement and mantain, so they've chosen to manually implement the async iteration interfaces.
I don't think we are talking about the same thing. I think it is totally fine to implement these interfaces yourself: usually when you implement a producer in a "low level" way you know what you are doing (cf Nodejs core maintainers).
I am talking about the code which consumes it, depending on the way you consume it, you might create leaks.
Consider the following producer (from my article I linked above):
constwait=delay=>newPromise(resolve=>{setTimeout(()=>resolve(),delay);});constcounterGen=asyncfunction*(limit=10,delay=100){letiter=1;try{while(true){if(iter>limit){break;}awaitwait(delay);yielditer;iter++;}}catch(e){console.log('oops something is wrong');throwe;}finally{console.log('I have been released !!!');}};
You could have written it by implementing the interfaces, it does not matter.
Just note it is doing some cleaning ("I have been released !!!"), it could be release file handle or whatever.
Now let's say you want to consume it and sum the 3 first values.
You can do it in a naive way
constsum=asynciterator=>{leti=0;letsum=0;while(i<3){constnext=awaititerator.next();if(next.done){break;}sum+=next.value;i++;}// VERY IMPORTANT IF YOU DO NOT WANT TO CREATE A LEAK// iterator.return();returnsum;};sum(counterGen()).then(console.log);
And this code creates a leak if you don't pay attention and do not explicitly call return (you will not see the release message)
Whereas if you decide to go for "native construct" like for await statement you are safe
Oh wow, this is next level! Also TIL about
for-await-of
; neat. Do you have some examples of where this can be really helpful in real world code? I'm wondering when I should think to maybe reach for this instead of cobbling something else together π Thanks!Thanks, I'm glad you liked the article π
Generally, the async iteration is well suited for all those circumstances where consumers should have control over the flow of data.
Next time I'll show some more concrete examples thanks to async generators, but for now a good starting point to satisfy your needs surely are Node.js Readable streams. WHATWG Streams are async iterables too.
I was thinking pagination could be a use case candidate for async iteration.
Yes of course. I've already briefly mentioned it into the 'The consumer pressure problem' section π
I think we can also write it down in this succinct way. But correct me if I'm wrong
Yes, but async gens are the argument of the next article eheheheh
SPOILER ALERT then :D eheh
A while back I also wrote a library to manipulate async stream with async iterables. You might find it interesting. It was in the context of this article.
It is a very nice serie you wrote here. However I think you should stress more on the fact that closing iterable is a leaky abstraction(by Reginald βRaganwaldβ Braithwaite). You did a bit in the second article but I think it deserves more attention. It is usually better to use built in consumers (such for await statement) to avoid problems
It could seem a stupid answer but I strongly believe in well-commented programs, so what is not immediately understandable should be highlighted with a proper comment/explanation.
I am with you, I think that custom implementations of interfaces like these should be kept to a minimum but...there is always an exception.
Like here: github.com/nodejs/node/blob/master...
One of the Node.js streams maintainer told me that an async gen would be too slow and hard to implement and mantain, so they've chosen to manually implement the async iteration interfaces.
I don't think we are talking about the same thing. I think it is totally fine to implement these interfaces yourself: usually when you implement a producer in a "low level" way you know what you are doing (cf Nodejs core maintainers).
I am talking about the code which consumes it, depending on the way you consume it, you might create leaks.
Consider the following producer (from my article I linked above):
You could have written it by implementing the interfaces, it does not matter.
Just note it is doing some cleaning ("I have been released !!!"), it could be release file handle or whatever.
Now let's say you want to consume it and sum the 3 first values.
You can do it in a naive way
And this code creates a leak if you don't pay attention and do not explicitly call
return
(you will not see the release message)Whereas if you decide to go for "native construct" like
for await
statement you are safeI think tutorials and articles on iterators (and async iterators) do not stress enough that eventual issue.
This was my point :)
Uh I've totally misunderstood your previous message!
Yes you are right, the
for-of
and thefor-await-of
should be always preferred π