Generators
The syntax function*
is used to define a generator and yield
is the analogue to return
for a generator.
What is?
Generator is considered as a special function, responsible for creating an iterator. It is characterized by calculating each item belonging to the eternal element at a time, rather than storing them all in memory, as is done without the generator. This feature is known for Lazy Evaluation.
Example
Consider the Fibonacci sequence, that each element consists of the sum of the two previous elements. Without using a generator, we could do:
function fibonacci(n) {
let sequence = [];
sequence.push(0, 1);
for (let i = 2; i < n; i++) {
sequence.push(sequence[i - 1] + sequence[i - 2]);
}
return sequence;
}
const sequence = fibonacci(10);
console.log(sequence.length);
The above code will generate an output equal to 10, referring to the number of positions stored in memory for the sequence. For small amounts, this would not affect the application, but if we consider a gigantesto value, such as a million elements, it would probably affect the yield of its application.
With the use of the generator:
function* fibonacci(n) {
let a = 0, b = 1, current;
while (true) {
current = a;
yield current;
a = b;
b = current + b;
}
}
const sequence = fibonacci(10);
for (let i = 0; i < 10; i++) {
console.log(sequence.next().value);
}
The elements of the list will not be in memory when we do const sequence = fibonacci(10)
, they shall be calculated within the for
, only when used, by sequence.next()
. But what if the list needs to have a million elements? No problem, as the elements are not in memory, the generator will not affect in your application (running time would remain high, as it would continue to run millions of operations, but in memory, would not be affected).
Iterator
The return of a generator is a iterator and therefore implements the next
.
Utilizing
Imagine that you want to display a list of all the names of the cities of Brazil, which total a number of approximately 5570, using Infinite scroll. Storing in memory the data from these 5570 records would be unnecessary, as the user will hardly use all of them. Then you could display on screen an initial amount, 20 for example, and when the user requires more, when reaching the end of the list, make, with the generator, an AJAX request to the server requesting 10 more records and adding them to the list. This way, the 5570 records would only be in memory if the user requested it.
Related
The Fibonacci sequence, although not widely used in practice, was used as an example due to ease of implementation.
Interesting! So for operations of this type it is convenient to use the mechanics of
yield
same? Since it has much less impact on memory usage..– Artur Trapp
Damn that answer. + 1
– Marconi
Thank you very much! If I could give +2 I would, because of the idea of using in Infinite scroll, which is a very common practice in my projects!
– Artur Trapp
@Arturtrapp, I added the comment to the reply.
– Woss
Is there any way to turn a generator into an array directly?
– Miguel
@Miguel, I believe with the
Array.from
, but I’m not sure.– Woss
@Andersoncarloswoss, no problem when I get home I see it. Good answer
– Miguel