Search code examples
javascriptiteratorgeneratortake

Why do JS generators terminate after a take() bottoms out?


I got tripped up by some behaviour of JS generators today. Iterators continue producing numbers after an IteratorHelper gotten by calling take() bottoms out, but generators, which should conform to the Iterator behaviour, do not:

iter = [1,2,3,4,5,6,7,8,9,10].values()

one = iter.take(3)
two = iter.take(3)
console.log(one.toArray())  // [1,2,3]
console.log(two.toArray())  // [4,5,6]

const gener = (function* () {
    for (var i = 1; i <= 10; i ++) {
        yield i
    }
})()

one = gener.take(3)
two = gener.take(3)
console.log(one.toArray())  // [1,2,3]
console.log(two.toArray())  // []

Why do generators behave like this? Am I just misusing them?

I haven't tried other Iterators besides the ArrayIterator in the code block above, but in any case I would have expected the behaviours of any Iterator and any Generator to be indistinguishable.

Tested on Chrome and Brave.


Solution

  • This happens because take executes the return method of the iterator if it has been implemented -- this implementation is optional. The generator prototype has an implementation of this method that finishes the generator.