Generators in JavaScript

E.Y.
3 min readNov 27, 2020

--

Photo by Louis-Etienne Foy on Unsplash

In the last blog, we were talking about Iterators and the pros and cons of it. So in this blog, we will be looking at Generators and how it is “better” than Iterators.

The Generator object is returned by a generator function and it conforms to both the iterable protocol and the iterator protocol.

It’s better than iterators in that Generator functions provide a powerful way to define an iterative algorithm by writing a single function whose execution is not continuous.

Generator functions are written using the function* syntax.

When called, generator functions return a special type of iterator, called a Generator. Whennext method gets called on the Generator, the Generator function executes until it encounters the yield keyword.

The function can be called as many times as desired, and returns a new Generator each time. However each Generator may only be iterated once.

See below an infinite loop Generator:

function* infinite() {
let index = 0;

while (true) {
yield index++;
}
}

const generator = infinite(); // "Generator { }"

console.log(generator.next().value); // 0
console.log(generator.next().value); // 1
console.log(generator.next().value); // 2
// ...
const newGenerator = infinite();console.log(newGenerator.next().value); // 0
console.log(newGenerator.next().value); // 1
console.log(newGenerator.next().value); // 2

To get the value using for...of loop:

for(let value of generator) { 
console.log(value); // 0,1,2
}

Accessing it using spread syntax:

[ …generator]; // 0, 1,2

Since Generator returns an iterator (noting the calling of next() ). The result of next() is always an object with two properties:

  • value: the yielded value.
  • done: true if the function code has finished, otherwise false.

How do we reach the last item in the iterator?

Well, each time a yield is encountered it measn the done is set to false . So to get the last item with done set to true , we use return keyword (Any yield after this return is ignored).

function * definite() {
yield 0;
yield 1;
return 2; // Generator ends.
}

Also note that a generator object is both an iterator and an iterable.

function * generatorExample() {
yield 0;
yield 1;
return 2;
}
console.log(typeof generatorExample.next);
// "function", because it has a next method, so it's an iterator
console.log(typeof generatorExample[Symbol.iterator]);
// "function", because it has an @@iterator method, so it's an iterable

The yield is a magical keyword that can do more things other than simply return a value and next() can do more things aside from retrieving the value.

  • passing argument to next()

The argument passed to next() will be received by yield :

function *gen(x){
yield x
return
}
const generator = gen(2)
gen.next() //{value: 2, done: false}
gen.next() //{ value: undefined, done: true}
  • passing a function to yield

Apart from returning values yield can also call function.

function *gen(x){
yield func()
return
}
function func (){
return "function called"
}
const generator = gen()
gen.next() //{value: "function called", done: false}
gen.next() //{ value: undefined, done: true}
  • delegating to another generator or iterable using yield* expression
function* gen() {
yield 3;
}
function* func() {
yield* gen();
}
const iterator = func();
iterator.next().value; // 3
  • async generators

To asynchronously generates a list of values (e.g. continuous calls to api), we can create an asynchronous generator.

async function* apiCall(start, end) {
for (let i = start; i <= end; i++) {
await new Promise(resolve => setTimeout(resolve, 1000));
yield i;
}
}
(async () => {
let generator = apiCall(1, 5);
for await (let value of generator) {
alert(value); // 1, 2, 3, 4, 5
}
})();

You can also chain the Promise:

generator.next().value.then(n => console.log(n)) // 1,2,3,4,5

In general, Generators are a special kind of Iterators using yield keyword and implementing iteration protocols. It is really useful in Lazy Evaluation as the value can be retrieved on demand and thus memory efficient.

There’s more to cover on Generator. I found resources on MDN very useful to get the basic right, so is reading python related concepts such as .

That is so much of it!

Happy Reading!

--

--

No responses yet