In short
A normal function runs start to finish in one go. A generator can pause in the middle, hand you a value, and continue later from exactly where it stopped.
Functions (`function*`) that can pause and resume execution using `yield`, producing a sequence of values lazily instead of all at once. Generators are useful when values should be produced lazily, allowing consumers to pause iteration and request the next value only when needed.

Think of it like this
Binge-watching a web series
You watch one episode, close the app, and next time it picks up at episode 4, not from the start. yield is the end of an episode. next() is pressing "play next episode". The show remembers where you were.
Watch it happen
Pausing and resuming episodes()
episodes()
1/7Calling the generator returns an iterator. No code inside has run yet.
The big ideas
What you need to know
function* and yield
The star marks a generator. Each yield pauses it and sends a value out.
Calling it doesn't run it
Calling a generator gives you an iterator object. The code inside starts only when you call next().
{ value, done }
Every next() returns an object with the yielded value and done, which becomes true when the generator finishes.
Lazy and endless
A generator makes values only when asked, so it can describe an infinite sequence without freezing.
See it in code
Walk through the code
1function* episodes() {2 yield "Ep 1";3 yield "Ep 2";4 return "Season over";5}6 7const show = episodes(); // nothing runs yet8console.log(show.next()); // { value: "Ep 1", done: false }9console.log(show.next()); // { value: "Ep 2", done: false }10console.log(show.next()); // { value: "Season over", done: true }11function* rollNumbers(start) {12 let n = start;13 while (true) yield n++; // infinite, but lazy14}15const ids = rollNumbers(101);16console.log(ids.next().value, ids.next().value); // 101 1021/5function* makes a generator. Each yield is a pause point.
while (true) is safe here because yield pauses the loop each time. It only runs again when you ask for the next value.
Save yourself the pain
Common mistakes
Oops
Expecting for...of or spread to include the return value.
Do this instead
They stop as soon as done is true and ignore the returned value. Use yield for every value you want in the loop.
Oops
Spreading an infinite generator, like [...rollNumbers(1)].
Do this instead
That never ends and freezes the tab. Take only what you need with next() or a loop that breaks.
Your mission
Roll number machine
Quick check
Using episodes() from above, what does [...episodes()] give?
Go deeper
- 1Write a simple generator that yields a sequence of numbers. Validate your understanding by applying it in a small practical example.
- 2Use a `for...of` loop to consume a generator's values. Verify the behavior with realistic data and handle the failure or empty state as well.
- 3Learn how generators power async iteration and libraries like Redux-Saga.
More topics at this stop
Stuck on this topic? Ask an Insider
Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.