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
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 🙂