“This is the 11th day of my participation in the First Challenge 2022. For details: First Challenge 2022.”
What is a generator
Generators are a new function control scheme in ES6 that gives you the flexibility to control when a function executes and when it pauses. A generator function is also a function, which differs from a normal function:
(1) Generator functions need * after function
(2) Generator functions use the yield keyword to control the execution and pause of functions
The Generator function returns a Generator.
A generator is essentially a special iterator.
Generator function
Foo is a generator function because it meets the criteria for generator functions: (1) function followed by *, (2) use yield to control the execution and pause of the function, and (3) when foo is called, it returns a generator object that is a special iterator. We can call the next method.
function* foo() {
console.log('Function starts executing');
const value1 = 100
console.log('First code:', value1);
yield
const value2 = 200
console.log('Second code:', value2);
yield
const value3 = 300
console.log('Third code:', value3);
yield
console.log('End of function execution');
}
Copy the code
When a generator function is called, we are returned with a generator object
const generator = foo()
// Start executing the first code
generator.next()
// Start executing the second code
generator.next()
generator.next()
generator.next()
generator.next()
generator.next()
generator.next()
Copy the code
The execution flow of generator functions
The execution of the function is paused when yeild is encountered and terminated when return is encountered.
function* foo() {
console.log('Function starts executing');
const value1 = 100
console.log('First code:', value1);
yield value1
const value2 = 200
console.log('Second code:', value2);
yield value2
const value3 = 300
console.log('Third code :', value3);
yield value3
console.log('End of function execution');
return '123'
}
const generator = foo()
console.log('Return value 1:', generator.next());
console.log('Return value 2:', generator.next());
console.log('Return value 3:', generator.next());
console.log('Return value 4:', generator.next());
Copy the code
Generator passing parameters
With yield we allow the function to pause the piecewise execution. Functions can pass arguments, so how do we pass arguments to segmented functions?
When we call next, we can pass it an argument that will be the return value of the previous yield statement.
function* foo() {
console.log('Function starts executing');
const value1 = 100
console.log('First code:', value1);
const n = yield value1
const value2 = 200 * n
console.log('Second code:', value2);
const count = yield value2
const value3 = 300 * count
console.log('Third code:', value3);
yield value3
console.log('End of function execution');
return '123'
}
const generator = foo()
console.log(generator.next());
console.log(generator.next(10)); // The second next argument is the return value of the first yield
console.log(generator.next(20));
Copy the code
What if we want to pass parameters to the first paragraph? We can pass arguments when a function is called.
function* foo(num) {
console.log('Function starts executing');
const value1 = 100 * num
console.log('First code:', value1);
const n = yield value1
const value2 = 200 * n
console.log('Second code:', value2);
const count = yield value2
const value3 = 300 * count
console.log('Third code:', value3);
yield value3
console.log('End of function execution');
return '123'
}
const generator = foo(5)
console.log(generator.next());
console.log(generator.next(10));
console.log(generator.next(20));
Copy the code
Generator terminates prematurely — return function
We can use return to terminate the generator prematurely, and then continue calling next without generating any more values.
function* foo(num) {
console.log('Function starts executing');
const value1 = 100 * num
console.log('First code:', value1);
const n = yield value1
const value2 = 200 * n
console.log('Second code:', value2);
const count = yield value2
const value3 = 300 * count
console.log('Third code:', value3);
yield value3
console.log('End of function execution');
return 123
}
const generator = foo(10)
console.log(generator.next());
console.log(generator.return(20));
Copy the code
The generator throws an exception — the throw function
We can catch exceptions inside the generator.
function* foo() {
console.log('Code starts executing');
const value1 = 100
try {
yield value1
} catch (error) {
console.log('Exception caught:', error);
yield 123
}
console.log('Second code continues execution');
const value2 = 200
yield value2
console.log('End of code execution');
}
const generator = foo()
console.log(generator.next());
console.log(generator.throw('error message'));
console.log(generator.next());
Copy the code