I am trying to understand javascript's Symbol.asyncIterator and for await of. I wrote some simple code and it throws an error saying:
TypeError: undefined is not a function
on the line which tries to use for await (let x of a).
I could not understand the reason for it.
let a = {}
function test() {
for(let i=0; i < 10; i++) {
if(i > 5) {
return Promise.resolve(`Greater than 5: (${i})`)
}else {
return Promise.resolve(`Less than 5: (${i})`)
}
}
}
a[Symbol.asyncIterator] = test;
async function main() {
for await (let x of a) { // LINE THAT THROWS AN ERROR
console.log(x)
}
}
main()
.then(r => console.log(r))
.catch(err => console.log(err))
I create an empty object a and insert a key Symbol.asyncIterator on the same object and assign it a function named test that returns a Promise. Then I use for await of loop to iterate over all the values that the function would return.
What am I doing incorrectly?
PS: I am on the Node version 10.13.0 and on the latest version of Chrome
To be a valid
asyncIterator, yourtestfunction must return an object with anextmethod that returns a promise of a result object withvalueanddoneproperties. (Technically,valueis optional if its value would beundefinedanddoneis optional if its value would befalse, but...)You can do that in a few ways:
You can do it completely manually (this doesn't try to get the right prototype):
You can do it half-manually writing a function that returns an object with an
asyncnextmethod (still doesn't try to get the right prototype):Or you can just use an
asyncgenerator function (easiest, and automatically gets the right prototype):About prototypes: All async iterators you get from the JavaScript runtime itself inherit from a prototype that provides the very basic feature of ensuring the iterator is also iterable (by having
Symbol.iteratorbe a function returningthis). There's no publicly-available identifer or property for that prototype, you have to jump through hoops to get it:Then you'd use that as the prototype of the object with the
nextmethod that you're returning: