Open In App
Related Articles

JavaScript Function Generator

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Report issue
Report

Generator-Function: A generator-function is defined like a normal function, but whenever it needs to generate a value, it does so with the yield keyword rather than return. The yield statement suspends the function’s execution and sends a value back to the caller, but retains enough state to enable the function to resume where it is left off. When resumed, the function continues execution immediately after the last yield run. 

Syntax : 

// An example of generator function
function* gen(){
     yield 1;
     yield 2;
     ...
     ...
}

Generator-Object : Generator functions return a generator object. Generator objects are used either by calling the next method on the generator object or using the generator object in a “for of” loop (as shown in the above program) 
The Generator object is returned by a generating function and it conforms to both the iterable protocol and the iterator protocol.

Example 1: In this example, we will see the creation of basic generator object.

javascript

// Generate Function generates three 
// different numbers in three calls
function* fun() {
    yield 10;
    yield 20;
    yield 30;
}
  
// Calling the Generate Function
let gen = fun();
console.log(gen.next().value);
console.log(gen.next().value);
console.log(gen.next().value);

                    

Output:

10
20
30

Example 2: This example code prints infinite series of natural numbers using a simple generator.

javascript

// Generate Function generates an 
// infinite series of Natural Numbers 
function* nextNatural() {
    let naturalNumber = 1;
  
    // Infinite Generation
    while (true) {
        yield naturalNumber++;
    }
}
  
// Calling the Generate Function
let gen = nextNatural();
  
// Loop to print the first
// 10 Generated number
for (let i = 0; i < 10; i++) {
  
    // Generating Next Number
    console.log(gen.next().value);
}

                    

Output:

1
2
3
4
5
6
7
8
9
10

Example 3: This example of how to manually return from a generator. 

javascript

let array = ['a', 'b', 'c'];
function* generator(arr) {
    let i = 0;
    while (i < arr.length) {
        yield arr[i++]
    }
}
  
const it = generator(array);
// We can do it.return() to finish the generator

                    

Encountering yield and yield*

  • yield: pauses the generator execution and returns the value of the expression which is being written after the yield keyword.
  • yield*: it iterates over the operand and returns each value until done is true.

Example 4: 

javascript

const arr = ['a', 'b', 'c'];
  
function* generator() {
    yield 1;
    yield* arr;
    yield 2;
}
  
for (let value of generator()) {
    console.log(value);
}

                    

Output:

1
a
b
c
2

Example 5: Another way to create iterable.

javascript

let createOwnIterable = {
    *[Symbol.iterator]() {
        yield 'a';
        yield 'b';
        yield 'c';
    }
}
  
for (let value of createOwnIterable) {
    console.log(value);
}

                    

Output:

a
b
c

Example 6: Return from a generator function.

javascript

function* generator() {
    yield 'a';
    return 'result';
    yield 'b';
}
  
let it = generator();
console.log(JSON.stringify(it.next()));
// {value: "a", done: false}
console.log(JSON.stringify(it.next()));
  // {value: "result", done: true}

                    

Output
{"value":"a","done":false}
{"value":"result","done":true}

Example 7: How to throw an exception from the generator.

javascript

function* generator() {
    throw new Error('Error Occurred');
}
const it = generator();
it.next();
  // Uncaught Error: Error Occurred

                    

Output:

 

Example 8: Calling a generator from another generator.

javascript

function* firstGenerator() {
    yield 2;
    yield 3;
}
  
function* secondGenerator() {
    yield 1;
    yield* firstGenerator();
    yield 4;
}
  
  
for (let value of secondGenerator()) {
    console.log(value)
}

                    

Output:

1
2
3
4

Limitation of Generators: You can’t yield inside a callback in a generator.

Example 9: In this example, we will try to give yield inside a generator function.

javascript

function* generator() {
    ['a', 'b', 'c'].forEach(value => yield value) 
    // This will give syntax error
}

                    

Output:

SyntaxError: missing ) after argument list

Example 10: Using async generators (for api call).

javascript

const firstPromise = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(1), 5000)
    })
}
  
const secondPromise = () => {
    return new Promise((resolve, reject) => {
        setTimeout(() => resolve(2), 3000)
    })
}
  
async function* generator() {
    const firstPromiseResult = await firstPromise();
    yield firstPromiseResult;
    const secondPromiseResult = await secondPromise();
    yield secondPromiseResult;
}
  
let it = generator();
for await (let value of it) {
    console.log(value);
}

                    

Output:

(after 5 seconds)
1 
(after 3 seconds)
2

Advantages of generators: They are memory efficient as lazy evaluation takes place, i.e, delays the evaluation of an expression until its value is needed.JavaScript use-case (generators)

  • Writing generators in redux-saga
  • JavaScript async-await (Implemented with promise and generators)

We have a complete list of Javascript Functions, to check those please go through Javascript Function Complete reference article.

Supported Browser:

  • Google Chrome 39 and above
  • Microsoft Edge 13 and above
  • Firefox 26 and above
  • Opera 26 and above
  • Safari 10 and above


Last Updated : 24 May, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads