JavaScript/Generators



The term generator denotes a technique to generate a sequence of 'anything': numbers, strings, rows of database queries, elements of an array, nodes of a DOM tree, ...

It's used to avoid any memory overloading, by splitting the data in small chunks.

To use them, you must define a generator function[1] first. Such functions are notated with an asterisk * directly behind the keyword function, e.g., function* myGenerator(){...}.

When called, the function will not run instantly. It only runs just before the first occurrence of a yield statement and returns a 'Generator object'. This 'Generator object' offers a next method. Calling next again and again returns the sequence elements one after the next. The elements arise by each yield that is reached within the generator function.

Examples

edit
  • The script generates a sequence of 4 integers.
function* fourInts() {  let int = 0;  while (int < 4) {  yield int; // each .next() receives the current value of 'int'  int++;  } } const gen = fourInts(); // creation alert(gen.next().value); // 0 alert(gen.next().value); // 1 alert(gen.next().value); // 2 alert(gen.next().value); // 3 alert(gen.next().value); // undefined 
  • Every next() call returns not only a value; there is also a boolean done. Hence you can call the generator in loops.
function* fourInts() {  let int = 0;  while (int < 4) {  yield int;  int++;  } } const gen = fourInts(); // creation do {  const tmp = gen.next();  if (tmp.done) {  break;  } else {  alert(tmp.value); // 0, 1, 2, 3  } } while (true) 
  • Generation out of an array, a database request, or a tree traversal.
function* arrayElements() {  // for simplicity, we use an array; database queries or tree traversals  // are more realistic.  const myArray = ["yellow", "green", "blue"];  for (const elem of myArray) {  yield elem;  } } const sequence = arrayElements(); // creation do {  const tmp = sequence.next();  if (tmp.done) {  break;  } else {  alert(tmp.value); // "yellow", "green", "blue"  } } while (true) 
  • Creation of the infinite sequence of all even numbers.
function* evenNumbers() {  for (let i = 0; true; i = i + 2) {  yield i;  } } const sequence = evenNumbers(); // creation let i = 0; while (i < 20) {  i = sequence.next().value;  alert(i); // 0, 2, 4, ... } 

Parameters

edit

The generator function may receive parameters. In this example, the 'pageSize' defines the number of array elements to be returned.

function* pagination(arr, pageSize) {  for (let i = 0; i < arr.length; i = i + pageSize) {  yield arr.slice(i, i + pageSize);  } } const arr = [1, 2, 3, 4, 5, 6, 7] const page = pagination(arr, 3); alert (page.next().value); // { value: [1, 2, 3], done: false } alert (page.next().value); // { value: [4, 5, 6], done: false } alert (page.next().value); // { value: [7], done: false } alert (page.next().value); // { value: undefined, done: true } 

References

edit