Generators are powering async / await functions under the hood. You might have a look at this code compiled from Typescript playground, which give you a nice sample of that.

In the right panel you’ll have the converted output of our generator code.

See the yield Promise.resolve("hello"); statement ? You are within a generator, that’s it.

Generators are really cool for any cycle based code such as state machine, sequencing or any game loop.

Speaking of game loop, the today article is about one card shuffling machine, which is kind of card picker loop system. You might already have seen such machine in a Casino ? This is used to shuffle cards for the dealer.

🃏My card shuffler class

What will follow is a simple implementation of a 52 cards classic deck shuffler.

✋🏻⚠️ This is not suitable for production uses as the random shuffling algorithm is a pseudo random shuffling one. If this function is called many times every seconds, it might results in duplicated entries.

💡You might be interested at reading this : https://www.random.org/randomness/ which give nice explanations about random values in computer science.

This shuffler will use lodash _.shuffle method to randomly shuffle an array which represent an entire 52 playing cards deck.

Lodash is a JS library that provide a great toolbox for many commons use cases.

The shuffling will be done using the Fisher–Yates shuffle algorithm, if you want to knows more about that, follow the link to Wikipedia.

All cards will be represented by the classic suit of diamonds (♦), clubs (♣), hearts (♥) and spades (♠) with their numbers.

Each iterations will return one pair of type — value representing the card, which allows to display the proper card in the UI.

Here is the interface contract for a GameCard:

interface GameCard {

type: ♥️ | ♦️ | ♠️ | ♣️,

value: "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" | "J" | "Q" | "K"

}

We could get a card as {"type": " ♠️ ", value:"1"} which represent the « As of spades 🂡 ».

💻 The entire code of the Card Shuffler in one snippet

❓How does it works ?

It’s pretty simple, everything stands in a three step process:

First, pass a deck as an array with any cards you which as argument to the CardShuffler constructor, it will shuffle the given cards for randomness. Then, initialize the generator iterator by calling getCardDrawer which returns our main tool for this game loop. Enjoy using generator by asking for new cards, over and over again until the deck get empty.

For the simplicity of the demonstration, the deck is only composed by 4 cards in the given example. Feel free to add a true 52 cards deck to reflect real life example and better randomness.

🎮 The game loop

Once you instantiated the GameShuffler class and the constructor shuffled the entire deck: you can call getCardDrawer method to obtain the iterator that will be used to draw each cards one by one.

➡️ There are two ways (at least) to iterate through the game loop:

❶ Iterate through generator manually using some kind of event

In that example we created a function that can be bound to any event handler such as a click on a button or manually trigger by calling that function.

Each generator’s iterator expose a .next method that will execute the code in the generator function to the next yield statement.

The interpreter will iterate the while loop each time to check for the deck size, and, if there is any remaining cards in the deck, will get one new by taking it from the deck.

It will then block the code execution at the yield statement, until we call one more time the iterator’s .next function.

const onClick = () => {

const nextCardStatus = cardDrawer1.next(); if (nextCardStatus.done) {

console.log("Deck is now empty!");

} else {

console.log("Picked card is: ", nextCardStatus.value.card);

console.log("Remaining cards in the deck: ", nextCardStatus.value.remainingCards);

}

};

Each time we draw a card from the deck, the card is being removed. Once the game deck is empty, we are exiting the loop and the generator complete.

You will need to instantiate a new CardShuffler to play another game.

❷ Using « for…of » operator to iterate through the generator

Generator’s iterators can also being used in Javascript language loops, that’s the case if we use the for…of operator which is part of the ES6 specification.

for (const cardStatus of cardDrawer2) {

console.log("Picked card is: ", cardStatus.card);

console.log("Remaining cards in the deck: ", cardStatus.remainingCards);

}

This allows us to iterate through the cards sequence as long as there are cards in the deck.

This is just kind of syntactic sugar that helps you looping through an iterator. But under the hood, this is simply calling the next method or the iterator and check for the done and value keys of the returning object to determine whether the generator has completed or not.

🚛 Takeaway / TLDR; 📦

Generators are nice tools that allows better async functionalities, infinite data streams, lazy evaluated, memory efficient iterations.

They can make your code more readable and performant by enhancing your loop processes. They are very powerful for state machine such as Redux-Saga has demonstrated.

They fit perfect for any sequence / loop based iteration on infinite data stream.

You should definitely give it a try!