Generators are an advanced concept in javascript but are quite easy to understand. Generators are special functions in javascript which can return multiple values on demand unlike regular functions which can only return one value.
Unlike normal functions, the execution of a generator function can be stopped midway and can be resumed.
How to create a generator function
There is a special syntax for creating a generation function which is not much different from the normal function syntax.
function* generatorFunction(){
}
The * after the function keyword is what makes this function a generator function.
How to use the generator function created above
Another keyword yield is introduced here. You can think of yield as the return keyword but for generator functions. Let's take an example here
function* generatorFunction(){
console.log("Start")
yield 7;
console.log("Midway")
yield 8;
console.log("Stop")
}
const gen = generatorFunction();
let result = gen.next();
console.log(result.value) // logs 7
result = gen.next();
console.log(result.value) // logs 8
Let's see what's happening here:
- We define a generator function which first yields (returns) the number 7 and then next yields the number 8. We also added a couple of console logs.
- We call the generatorFunction here and store the return value in the variable
gen
- Normally when using normal functions you will expect the
gen
variable to hold the value 7. - But that's not the case for generators. The
gen
variable doesn't store the value yielded by the generator, instead it stores aGenerator
object returned bygeneratorFunction
- The
gen
object has a methodnext()
- The first call of the
gen.next()
method starts the execution of the generator function and when it reaches ayield
, it stops the function there and returns an object which has 2 propertiesvalue
anddone
. Value is the yielded value and done is a boolean which tells us whether the generator function is done completely executing or not - So in the above example, when
gen.next()
is called for the first time, the generator function starts executing. "Start" is logged to the console and then the generator yields a value of 7. That's when it stops the function and returns an object, which (in this case) will be{ value : 7 , done : false }
. value is the yielded value which is 7. done isfalse
because the generator is not completely executed yet; there are still some lines of code in the function yet to be executed. "7" is logged to the console. - The next (second) call of the
gen.next()
method resumes the generator function from the point it stopped at before. Thus, "Midway" is logged to the console and then the generator yields a value of 8. It stops the function there and returns{ value: 8, done: false}
since the yielded value is 8 and the function is still not done executing. "8" is logged to the console. - "Stop" is never logged to the console since we never call
gen.next()
again
Notes
- In the above example, if we call
gen.next()
for a third time, "Stop" will be logged on the console and the object returned would be{value : undefined, done : true}
. Notice how this time the done property is true? That's because all the code of the generator is done executing. Whereas the value property is undefined? That's because no value has been yielded by the generator. If you keep callinggen.next()
after this, the result will always be{value : undefined, done : true}
-
A generator object cannot be restarted. Once it's done completely executing, you cannot restart it. If you want to run a generator function again make a new
Generator
object by callinggeneratorFunction
and store it in a new variable. Then you can work with that variable.-
Example :
const newGen = generatorFunction(); const newResult = newGen.next(): console.log(newResult).value) // logs 7
-
Top comments (2)
Here's a potential usage/implementation of a generator. This example will demonstrate how to use a generator to extract odd numbers from a list.
Here's a quote about generators from another language which could provide some context as to what they're for and why to use them:
"Generators provide an easy way to implement simple iterators without the overhead or complexity of implementing a class that implements the Iterator interface.
A generator allows you to write code that uses foreach to iterate over a set of data without needing to build an array in memory, which may cause you to exceed a memory limit, or require a considerable amount of processing time to generate."
Yup. This is a good potential use. Thanks Matt