Understanding Generators in JavaScript with examples

First of all: what is Generators in js?🤔

Generators are functions.
Generator Function Run Its Code When Required.
Generators Are iterables.
It doesn’t run unless you need it.
Generator Function Return Special Object [Generator Object].
That…


This content originally appeared on DEV Community 👩‍💻👨‍💻 and was authored by Hamza Elkotb

First of all: what is Generators in js?🤔

  1. Generators are functions.
  2. Generator Function Run Its Code When Required.
  3. Generators Are iterables.
  4. It doesn't run unless you need it.
  5. Generator Function Return Special Object [Generator Object].
  6. That Object can loop on generator function data.

❗NOTE: The data is present but when the function run, it generates the data.

Briefly:

Generators functions are different from normal function it doesn't run until you need it, they are iterable & return special object.

Image description

Example from real live:

like tickets generator device, when you pay it generates new serial number and print on new ticket then you get it, Here serial number already exists but it didn't print until get order to create a new ticket.

Generators Methods:

next() to get next yield.
return() to return a value & stop generating.
throw() to throw an error & stop generating.

Generators properties:

done if iteration done or not, return boolean value.
value current yield value.

Syntax:

function* generatorName(){
}

Now you can put in it any JS code and also can add the data that want to generate and we'll see how in next paragraph👇.

Yield Data | Data Production Process

Yield keyword used to data production process, and then you can loop on it using next() with Generator Object.

so you use yield keyword and put it's value.

function* generatorName(){
  yield "hello";
  yield "bye";
  yield 1;
  yield 2;
}

you can put any type of data (boolean, object...)

lets try Looping on Generator function Yields🔃

for (let i of generateNums()){
  console.log(i);
}

the output will be:
"hello"
"bye"
1
2
this also what next() method does!

Create Generator Object🏭

let generator = generatorName();

lets see something will make this clear to you💯
lets check typeof

console.log(typeof generator); // object
console.log(typeof generatorName); // function
console.log(generator); // Object: Generator {...}

next method | Accessing Yields

It returns value & done state

console.log(generator.next()); // Object { value: "hello", done: false }
console.log(generator.next()); // Object { value: "bye", done: false }
console.log(generator.next()); // Object { value: 1, done: false }
console.log(generator.next()); // Object { value: 2, done: false }

As you note every time you use next() method, it returns the next yield and can't undo this action.⏩

Now we looped on all yields, if we use next() again guess what we'll happen!🤔

console.log(generator.next()); // Object { value: undefined, done: true }

yes, it returned value: undefined that's because there is no more yield to access, also you'll find done: true because loop is over.

value property:

Use it with next() method to get the current yield value.

console.log(generator.next().value); // undefined

I want you to think why it returned undefined.🤔
I'll be 😊 if you answered it true in comments.

done property:

console.log(generator.next().done); // true

return & throw Methods | Controlling yield process

1- return

Use return method to stop yielding process, making done:true & value: undefined also you can return a custom value.
Let's see an example😬

these are our generator function & generator object:

function* letter(){
  yield "A";
  yield "B";
  yield "C";
}
let gen2 = letter();

also we can access normally:

console.log(gen2.next()); // Object { value: "A, done: false }
console.log(gen2.next()); // Object { value: "B", done: false }

Now if we used return method this is what will happen

console.log(gen2.return()); // Object { value: undefined, done: true }

As you noticed we still have one yield we didn't access it before, plus if you used next() method again you'll get { value: undefined, done: true }.
that is what return is here to do!

also you can return any value, by putting it between ()

console.log(gen2.return("visit youtube.com/devcoder")); 

now output will change to { value: "visit youtube.com/devcoder", done: true }.

2- throw

It's like return() method, but it throws custom errors like throw keyword.

let gen3 = letter();
console.log(gen3.next()); // Object { value: "A, done: false }
console.log(gen3.throw("Hi coder!")); // Error: Uncaught Hi coder!
console.log(gen3.next()); // not working

❗NOTE: throw() method doesn't stop your code, just stop the generator object.

Use Case: for example we have a generator function to generate random numbers, if that number is duplicated, it throws error.

Loop on generator yields

if we tried to loop through gen2 no output will appear

for (let i of gen2){
  console.log(i);
}

that's because we already accessed gen2 in past examples, so will create new generator object and loop though

let gen4 = letter()
for (let i of gen4 ){
  console.log(i);
}

try that, will work.✅

Generate Infinite Numbers

function* infinity(){
  let index = 0
  while(true){
    yield index++
  }
}
let inf = infinity();

Now as you see we're able to add normal JS code inside generator function,
1- when inf visit infinity() for first time index = 0 and will enter the infinite loop and will not exit
2- in loop, every time we use next(), index will increment and yield will equal the new index value.

NOW, let's use next() on it

console.log(inf.next()); // Object { value: 0, done: false }
console.log(inf.next()); // Object { value: 1, done: false }
console.log(inf.next()); // Object { value: 2, done: false }
console.log(inf.next()); // Object { value: 3, done: false }
...

🔴IMPORTANT

yield*

What is deference between yield & yield*, the answer will be clear if we try it with an array.👇

function* GeneAll(){
  yield* [4,5];
  yield [6,7];
}

let gen754 = GeneAll()

Now let's try to access for one time

console.log(gen754.next()); // Object { value: 4, done: false }

as you noticed it returned only the first element from our array.
let's try again!

console.log(gen754.next()); // Object { value: 5, done: false }

Now it returned the second element.
let's try again!

console.log(gen754.next()); // Object { value: [6,7], done: false }

But now it returned the full array, why???🤯

the yield* treat value as individual elements, so it converts the array value into more small values, but yield doesn't do this.
The same thing applies to string!

Delegate Generator Function | (Generator Function Chaining)

  • it's a function that delegate another function yield

take an example🎴

function* nums(){
  yield 1;
  yield 2;
  yield 3;
}

function* letter(){
  yield "A";
  yield "B";
  yield "C";
}

function* AllYields(){
  yield nums(); // without starter"*" will return the name of function
  yield* nums(); // this will include an array contains all nums() yields
  yield* letter()
  yield [6,7]; // without starter"*" it'll return an array
}

let gen55 = AllYields()

Let's see what will happen in first next()

console.log(gen55 .next()); // Object { value: Generator, done: false }

as you saw it returned the function name

console.log(gen55.next()); // Object { value: 1, done: false }
console.log(gen55.next()); // Object { value: 2, done: false }
console.log(gen55.next()); // Object { value: 3, done: false }

What happened behind the since?🤯
1- gen55 will go to every yield and enter it to access all data in it.
2- it will find that first yield without * and contains a generator function nums().
3- will return it's name.
4- after that gen55 will go to next yield "yield* nums()" with * so, will go through it.
5- it will find that it contains other yields so, will go through every yield and return it on every next() method call until it end accessing all nums() yields.
6- and now it went through out our second yield "yield* nums()" .
7- Then go to next yield in AllYields() and repeat the same process etc...

Conclusion

This was all what I know about generators in javascript, I hope you enjoyed with this article and learned a new thing,
I'll be happy for that.
If you have any notes about this article or new information tell me about in comments.
Follow me on YouTube , GitHub .
For Coding T-shirts visit: CodingShirts .
And don't forget to read these references👇.
See you again, Bye👋

References

MDN: Generator
MDN: function*
MDN: Iterators and generators
digitalocean: understanding generators in JS
JavaPoint: ES6 Generators


This content originally appeared on DEV Community 👩‍💻👨‍💻 and was authored by Hamza Elkotb


Print Share Comment Cite Upload Translate Updates
APA

Hamza Elkotb | Sciencx (2022-10-09T18:21:36+00:00) Understanding Generators in JavaScript with examples. Retrieved from https://www.scien.cx/2022/10/09/understanding-generators-in-javascript-with-examples/

MLA
" » Understanding Generators in JavaScript with examples." Hamza Elkotb | Sciencx - Sunday October 9, 2022, https://www.scien.cx/2022/10/09/understanding-generators-in-javascript-with-examples/
HARVARD
Hamza Elkotb | Sciencx Sunday October 9, 2022 » Understanding Generators in JavaScript with examples., viewed ,<https://www.scien.cx/2022/10/09/understanding-generators-in-javascript-with-examples/>
VANCOUVER
Hamza Elkotb | Sciencx - » Understanding Generators in JavaScript with examples. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2022/10/09/understanding-generators-in-javascript-with-examples/
CHICAGO
" » Understanding Generators in JavaScript with examples." Hamza Elkotb | Sciencx - Accessed . https://www.scien.cx/2022/10/09/understanding-generators-in-javascript-with-examples/
IEEE
" » Understanding Generators in JavaScript with examples." Hamza Elkotb | Sciencx [Online]. Available: https://www.scien.cx/2022/10/09/understanding-generators-in-javascript-with-examples/. [Accessed: ]
rf:citation
» Understanding Generators in JavaScript with examples | Hamza Elkotb | Sciencx | https://www.scien.cx/2022/10/09/understanding-generators-in-javascript-with-examples/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.