🍪 JavaScript Generator Functions: The Magical Cookie Maker
Once upon a time in a cozy little code kitchen, there was a magical cookie maker. But it wasn’t your usual cookie machine. No no! This one had superpowers…
It didn’t dump all the cookies out at once like most machines.
Instead, it had a secret: it could pause and wait, give you a cookie one by one, and continue only when you were ready!
🧙♂️ Meet the Wizard Function*
In JavaScript, we tell the computer, “Hey, this is going to be a magical cookie maker!” by writing:
function* cookieMaker() {
yield "Chocolate Chip Cookie 🍪";
yield "Oatmeal Raisin Cookie 🍪";
yield "Peanut Butter Cookie 🍪";
}
Notice that little star (*
) after function
? That’s the twinkle of magic. It tells JavaScript, “This is not just any function. This is a generator — a cookie maker that gives cookies slowly!”
Now, when we start this generator, it doesn’t immediately give us all three cookies.
It gives us something better: 🎮 A remote control (called an iterator).
const cookies = cookieMaker();
Now cookies
holds our magical remote, and we can press the next()
button whenever we want to get a cookie!
🍪 How It Works: One Cookie at a Time
Let’s press the button!
console.log(cookies.next());
🎉 Output:
{ value: 'Chocolate Chip Cookie 🍪', done: false }
“Here’s your first cookie! I’ll wait right here until you ask for the next one.”
When we press again:
console.log(cookies.next());
Output:
{ value: 'Oatmeal Raisin Cookie 🍪', done: false }
And again:
console.log(cookies.next());
Output:
{ value: 'Peanut Butter Cookie 🍪', done: false }
One more time?
console.log(cookies.next());
Output:
{ value: undefined, done: true }
😢 “No more cookies! I’m all done.”
🛑 Stopping the Cookie Machine Early — return()
Let’s say you only want one cookie and no more. You can politely tell the cookie maker:
cookies.return("I’m full!");
This will return:
{ value: "I’m full!", done: true }
And the machine is now officially retired. It won’t make any more cookies.
😱 Oh No! A Cookie Burned — throw()
Imagine one cookie got burnt!
You can tell the cookie maker:
cookies.throw(new Error("Burnt cookie!"));
The generator will stop immediately and JavaScript will treat this as an error — unless you catch it.
🧁 Adding Ingredients with next(value)
Now here’s something REALLY magical.
Let’s say the cookie maker pauses and asks: “What flavor should the next cookie be?”
You can send it an ingredient like this:
function* customCookieMaker() {
const flavor = yield "What flavor do you want?";
yield `Here’s your ${flavor} cookie! 🍪`;
}
const custom = customCookieMaker();
console.log(custom.next()); // Ask: What flavor?
console.log(custom.next("Strawberry")); // Answer: Strawberry
Output:
{ value: 'What flavor do you want?', done: false }
{ value: 'Here’s your Strawberry cookie! 🍪', done: false }
Whoa! We gave it a flavor, and it baked the cookie using our input!
🧑🍳 Teamwork with yield*
– Let the Sprinkle Chef Help
Sometimes, our cookie maker might say:
“I need help adding sprinkles. Let my sprinkle chef do that.”
So we use:
function* sprinkleChef() {
yield "Rainbow Sprinkles 🌈";
yield "Chocolate Sprinkles 🍫";
}
function* bigChef() {
yield "Mixing Dough...";
yield* sprinkleChef(); // Let the sprinkle chef do his job
yield "Baking Cookies...";
}
When we run bigChef()
, we’ll get all the steps — including those from sprinkleChef
— in order!
🔄 Want All Cookies at Once? Use a for...of
Loop!
Tired of pressing next()
again and again? 😅
Just say:
for (let cookie of cookieMaker()) {
console.log(cookie);
}
Output:
Chocolate Chip Cookie 🍪
Oatmeal Raisin Cookie 🍪
Peanut Butter Cookie 🍪
So neat! The for...of
loop presses next() for you automatically — until it gets to done: true
.
📦 Waiting for Ingredients — Async Magic
Let’s pretend the cookie maker needs to wait for chocolate chips to be delivered online. You don’t want your whole kitchen to freeze while waiting.
Generators were the first way JavaScript handled pauses in time without freezing.
These days, JavaScript uses async
and await
for that. But guess what? async/await
was inspired by generators!
async function bakeCookies() {
const delivery = await getChocolateChips();
console.log(`Baking with ${delivery}!`);
}
Just like a smart generator, async
functions also pause and resume when the data arrives.
📝 Review Questions (Practice Time!)
- 🧁 What does the
*
infunction*
mean in JavaScript? - 🍪 What happens when a generator reaches a
yield
keyword? - 🎮 What does calling
.next()
on a generator return? - 🛑 How do you tell a generator to stop early and return a final value?
- 🍫 What does
yield*
allow one generator to do with another?