Skip to content

Instantly share code, notes, and snippets.

@androide-osorio
Created October 4, 2016 21:36
Show Gist options
  • Save androide-osorio/94123e4c2389fc47e1cb88b7257529ad to your computer and use it in GitHub Desktop.
Save androide-osorio/94123e4c2389fc47e1cb88b7257529ad to your computer and use it in GitHub Desktop.
ES2015 roadtrip to awesomeness: Generators
/**
* ES2015 Generators
*/
// think of ES2015 generators as a new kind of function,
// which may be paused in the middle, one or many times,
// and resumed later, allowing other code to run during these
// periods of pause, and be passed different information
// each time it is started or paused, and respond accordingly
// to create a generator function,
// append an * to the "function" keyword
function* listPeople() {
// use "yield" expression every time
// you need to send something "out" when
// pausing the generator
yield 'Andrew';
yield 'Cesar';
yield 'Linis';
// yield can be used without any expression at the right.
// in these cases, it will just put out "undefined"
}
// generator functions do not get called immediately
// like normal functions. Instead, they return a
// generator object.
const people = listPeople();
// now, you can access the values the generator yields using the .next() method.
// This method returns an object with the requested value
// and a boolean that indicates if the generator function
// is done with all its values (and therefore, it not return anything else)
console.log(people.next()); // { value: 'Andrew', done: false }
console.log(people.next().value); // -> "Cesar"
console.log(people.next().done); // -> false
console.log(people.next().value); // -> "Linis"
console.log(people.next().value); // -> undefined
console.log(people.next().done); // -> true
//-------------------------------------------------------------------------------
// scope in generator functions
// when declaring variables inside a generator,
// they retain their values until all the
// yield expressions are complete.
function* listScientists() {
const scientists = [
{ name: 'Isaac Newton', profession: "physicist" },
{ name: 'Galileo Galilei', profession: "astronomist" },
{ name: 'Alan Turing', profession: "computer scientist" },
{ name: 'Gottfried Wilhelm Leibniz', profession: "mathematician" },
{ name: 'Michel Foucault', profession: "philosopher" },
{ name: 'Amedeo Avogadro', profession: "chemist" }
];
for(const scientist of scientists) {
yield scientist;
}
}
const scientistList = listScientists();
console.log(scientistList.next().value.name); // -> Isaac Newtown
// NOTE: the "scientist" constant inside the generator
// is not being re-declared here
console.log(scientistList.next().value.name); // -> Galileo Galilei
// ----------------------------------------------------------
// the next() method can receive a value. This value is passed in
// to the generator and returned by the current yield expression
function *complicatedMath(x) {
var y = 2 * (yield (x + 1)); //(1)
var z = yield (y / 3); // (2)
yield (x + y + z); //(3)
}
const algebra = complicatedMath(5);
console.log(algebra.next().value); // -> 6 (1)
console.log(algebra.next(12).value); // -> 8 (2)
console.log(algebra.next(13).value); // -> 42 (3)
// ----------------------------------------------------------
// generators return a data type that is iterable
// (i.e: implements Symbol.iterator). Therefore, we can
// use for..of to loop through a generator
for(const scientist of listScientists()) {
console.log(scientist.name);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment