DEV Community 👩‍💻👨‍💻

Erik Smith
Erik Smith

Posted on

Animals and Onions: A Basic JavaScript Generator

Demonstrate the basic syntax and use of a JavaScript generator function*. Replit demo here.

Creating a randomAnimalGeneratorFunc

First, we create a Generator function that stores a list of animals (and an onion). As the Generator is iterated, a random animal (or an onion!) is yielded and then removed from the list.

function* randomAnimalGeneratorFunc() {
  let animals = [
    "🧅",
    "cat",
    "dog",
    "hamster",
    "bird",
    "snake",
    "turtle",
    "guinea pig",
    "horse",
    "fish",
    "mouse",
    "lemur",
    "whale",
    "crab",
  ];

  while (animals.length) {
    const i = Math.floor(Math.random() * animals.length);
    yield animals[i];
    animals.splice(i, 1);
  }
}
Enter fullscreen mode Exit fullscreen mode

Notice how code after the yield statement is reachable and executed, which is very different from a standard function return statement.

Assigning the Generator to variables

The randomAnimalGeneratorFunc() function is a Generator function. Each time it is called, it returns a new Generator which we can assign to a variable.

const randomAnimalGenerator = randomAnimalGeneratorFunc();
const anotherRandomAnimalGenerator = randomAnimalGeneratorFunc();
Enter fullscreen mode Exit fullscreen mode

In the example above, randomAnimalGenerator and anotherRandomAnimalGenerator are two distinct Generators. Removing items from the animals list in randomAnimalGenerator has no direct effect on the animals list in anotherRandomAnimalGenerator.

Note that if you have a more complex data structure with nested references to arrays or objects stored in variables declared outside of the Generator function's scope, those referenced objects will experience side-effects across Generators as expected.

An animal function

const randomAnimalGenerator = randomAnimalGeneratorFunc();

const animal = () => {
  const a = randomAnimalGenerator.next();

  if (!a.done) {
    return a.value === "🧅" ? "🧅🧅🧅🧅 Onions!!!!" : a.value;
  }

  return `You're out of animals (and onions).`;
};

Enter fullscreen mode Exit fullscreen mode

The animal function will return a random animal from the animals list in randomAnimalGenerator. If an onion is encountered, you will be notified and may use the information in your RCA report. When you've gone through the entire animals list, you will have to reload the app to start over because I didn't bother writing a reset function.

An onion function

const randomAnimalGenerator = randomAnimalGeneratorFunc();

const onion = () => {
  let o = randomAnimalGenerator.next();

  while (!o.done) {
    if (o.value === "🧅") {
      return "🧅🧅🧅🧅 Onions!!!!";
    }
    console.log(o.value);
    o = randomAnimalGenerator.next();
  }

  return `You're out of animals (and onions).`;
};
Enter fullscreen mode Exit fullscreen mode

The onion function will return a randomized list of all the animals in the animals list. If an onion is encountered, execution will be halted to alert you of the danger. Running the onion function a second time will return the remaining animals in random order. You will be notified when the animals list is empty.

Putting it all together

function* randomAnimalGeneratorFunc() {
  let animals = [
    "🧅",
    "cat",
    "dog",
    "hamster",
    "bird",
    "snake",
    "turtle",
    "guinea pig",
    "horse",
    "fish",
    "mouse",
    "lemur",
    "whale",
    "crab",
  ];

  while (animals.length) {
    const i = Math.floor(Math.random() * animals.length);
    yield animals[i];
    animals.splice(i, 1);
  }
}

const randomAnimalGenerator = randomAnimalGeneratorFunc();

const animal = () => {
  const a = randomAnimalGenerator.next();

  if (!a.done) {
    return a.value === "🧅" ? "🧅🧅🧅🧅 Onions!!!!" : a.value;
  }

  return `You're out of animals (and onions).`;
};

const onion = () => {
  let o = randomAnimalGenerator.next();

  while (!o.done) {
    if (o.value === "🧅") {
      return "🧅🧅🧅🧅 Onions!!!!";
    }
    console.log(o.value);
    o = randomAnimalGenerator.next();
  }

  return `You're out of animals (and onions).`;
};
Enter fullscreen mode Exit fullscreen mode

See that I've defined randomAnimalGenerator outside of the animal and onion functions to demonstrate how both functions share the same Generator and any side-effects created by animal have an impact on onion and vice versa.

P.S., I love onions! 🧅

Top comments (1)

Collapse
 
Sloan, the sloth mascot
Comment deleted

We are hiring! Do you want to be our Senior Platform Engineer? We're hiring for a Senior Platform Engineer and would love for you to apply.

Head here to learn more about who we're looking for.