Search code examples
javascriptgenerator

Javascsript generator confusing behavior


I came across this article explaining generators https://modernweb.com/replacing-callbacks-with-es6-generators/

Which contains this example

function* ticketGenerator() {
  for (var i = 0; true; i++) {
    var reset = yield i;
    if (reset) {
      i = -1;
    }
  }
}

var takeANumber = ticketGenerator();
console.log(takeANumber.next().value); //0
console.log(takeANumber.next().value); //1
console.log(takeANumber.next().value); //2
console.log(takeANumber.next(true).value); //0          <----- Why is this happening?
console.log(takeANumber.next().value); //1

What confuses me is the output of the console.log(takeANumber.next(true).value); line which is unintuitive.

Why wouldn't it print 0 1 2 3 0 instead of 0 1 2 0 1 ?

I tried running it in console to make sure there wasn't an error in the article but it worked as the article stated


Solution

  • You can look at it step by step using Python Visualizer (which can also visualize JavaScript). See here.

    What happens is this:

    • You call next() for the first time. The generator code runs from the beginning to the function until it reaches yield 0. The value 0 is returned and execution is paused.
    • You call next() for the second time. The generator code receives undefined as return value from the previous yield and continues execution until it reaches yield 1. The value 1 is returned and execution is paused.
    • You call next() for the third time. The generator code receives undefined as return value from the previous yield and continues execution until it reaches yield 2. The value 2 is returned and execution is paused.
    • You call next(true). The generator code recevies true as return value from the previous yield and resets the counter to -1. It then continues execution until it reaches yield 0. The value 0 is returned and execution is paused.
    • You call next() for the last time. The generator code receives undefined as return value from the previous yield and continues execution until it reaches yield 1. The value 1 is returned and execution is paused.