A normal function runs until it returns. A generator can pause partway through: `yield` produces a value, suspends execution without blocking the main thread, and leaves the generator ready to continue when asked. Declare a generator with `function*`; calling it creates an iterator rather than running its body immediately. section 6.2 section 6.2.1
Call the iterator’s `next()` method to run to the next `yield`. Each call returns an object with `value` and `done` properties. A `for-of` loop can request yielded values for you instead of making those calls yourself. section 6.2.1
A value goes out; another comes back
`function* exchange() { const reply = yield "Ready"; yield "Received: " + reply; }` Calling `exchange()` creates an iterator. Its first `next()` yields `"Ready"`. Calling `next("yes")` resumes execution, makes the suspended yield expression evaluate to `"yes"`, and yields `"Received: yes"`. section 6.2.3
Two useful variations:
- Use `yield*` to yield values from another generator as part of the sequence. section 6.2.1
- Use the iterator’s `throw()` method to send an exception into a suspended generator, where it can be caught. section 6.2.3









