DEV Community

Discussion on: Use-Cases For JavaScript Generators

Collapse
 
emnudge profile image
EmNudge

I've found some more cases personally that have actually helped and are much smaller examples. My 3 favorites are:

  • for loops which need to be paused and resumed at a later date
  • infinitely looping over an array and having it reset to the beginning once it's done
  • creating iterables to use in for of loops from non-iterable objects using [Symbol.Iterator]

Generators also help to loop through structures where you'd normally need to keep track of multiple variables at a time. Instead of having multiple pieces of global state, you just need to call .next() on the generator.

I'd like to hear more about generators being a mistake though. I haven't yet heard that and I would like to know the reasoning behind it.

Cheers!

Collapse
 
rfornal profile image
bob.ts

Love the comments.

As to Generators being a mistake, I heard that in a talk a while back and vaguely remember agreeing with the arguments at the time. Since I can't remember the talk or the arguments, I'll change the language here.

Thanks again!
Bob

Collapse
 
rfornal profile image
bob.ts

Can you provide "practical" code uses with your examples that I can include?

Collapse
 
emnudge profile image
EmNudge

Here is the first example (looping arrays using generators to pause and resume):

function* makeGenLoop(arr) {
  for (const item of arr) {
    yield item;
  }
}

const myGen = makeGenLoop([0, 3, 7, 2, 5]);
console.log(myGen.next());
Enter fullscreen mode Exit fullscreen mode

Here is the infinitely looping array:

function* makeGenLoop(arr) {
  for (let i = 0;; i++) {
  if (i === arr.length) i = 0;
    yield arr[i];
  }
}

const myGen = makeGenLoop([0, 3, 7, 2, 5]);
console.log(myGen.next());
Enter fullscreen mode Exit fullscreen mode

Here is how to make an iterable from an object:

const myObj = {
  name: 'Stanley', 
  Job: 'Web Dev', 
  age: 28
}

myObj[Symbol.iterator] = function* () {
  for (const prop in this) {
    yield this[prop];
  }
}

console.log([...myObj]); // > ["Stanley", "Web Dev", 28]
for (const val of myObj) {
  console.log(val)
}
Enter fullscreen mode Exit fullscreen mode

and using a similar method, you can convert objects to Maps, which can become super useful in some instances:


const myObj = {
  name: 'Stanley', 
  Job: 'Web Dev', 
  age: 28
}

myObj[Symbol.iterator] = function* () {
  for (const prop in this) {
    yield [prop, this[prop]];
  }
} 

const objectMap = new Map(myObj);
console.log(objectMap.get('name')); // > "Stanley"
Enter fullscreen mode Exit fullscreen mode
Thread Thread
 
rfornal profile image
bob.ts

OK, the code examples are good ... and I get where you are going with this.

By "practical," I am trying to find actual use-cases ... not just "Hello World" type of code.

Thread Thread
 
emnudge profile image
EmNudge

I'm not going to bootstrap an entire project for an example, but I can give you a basic use case for them:

  1. You'd want to play and pause loops if someone hit a pause button on an animation and the loop is a tween.
  2. You'd want an infinitely looping array for things like carousels or lists of data which wrap around
  3. You'd want to iterate over objects to check if any of its properties include a specific value. You get the array and then check with .includes()
  4. You'd want a map if you have objects already and want to keep the object like structure, but also want to check if properties exist on an object that are falsy.

I hope you understand that I'm not going to code these entire use cases. It's be much too long for a comment and I'd sooner make my own post than a comment with the full code.

Thread Thread
 
rfornal profile image
bob.ts

This is more than enough ... if you are OK with it, I'll do a follow-up post to this one with your examples included (attributed to you, of course) down the road.

Thread Thread
 
emnudge profile image
EmNudge

Sounds good.
If you want one or two more, Dr. Axel Rauschmayer provides some use cases with async code

Thread Thread
 
rfornal profile image
bob.ts

Awesome ... thanks for the additional references!

Thread Thread
 
johannes5 profile image
Johannes5

@emnudge regarding your examples:
Could you explain / demonstrate 4. ?

I'm also not sure if I understand 3.
Why not use object.values().includes() ?

Thread Thread
 
emnudge profile image
EmNudge

Hey there! Just saw this now.
We can iterate through objects in many ways. The demonstration was showing that we can also iterate through objects in particular ways, as per our own use case.

We might want to create an iterator that only spits out object properties that are numbers or fall under some filter.
We could create an array of all properties and then filter, but this is creating 2 arrays whereas a generator allows us to create 0 arrays. We simply iterate over the returned iterable and deal with it as necessary

Thread Thread
 
rfornal profile image
bob.ts • Edited

I love the idea of using a generator for this. I might have to try an alternate!