Generators
Samuel Silva
What is a generator?
When standard Javascript functions are invoked, they run until they return a value or reach the end of the function. At that point, they’re finished. ES6 introduces a new type of function called generators.
A generator is a special type of function that can be entered and exited a number of times. You might hear people describe it as, “a function that can be paused”.

Functions vs. Generator Functions
function test() {
console.log('This')
console.log('is')
console.log('a')
console.log('test')
}
test(); // This is a test
function* testGenerator() {
console.log('This')
console.log('is')
console.log('a')
console.log('generator')
console.log('test')
}
testGenerator(); // Nothing here
Invoking Generators
function* testGenerator() {
console.log('This')
console.log('is')
console.log('a')
console.log('generator')
console.log('test')
}
const generator = testGenerator(); // Return a Generators instance
generator.next(); // Remember Iterators?
This executes the entire generator function by using a single .next() method because we haven’t established a point for where to pause / exit our function. We’ll do this below by introducing the yield keyword.
Pausing a generator
function* testGenerator() {
console.log('This')
console.log('is')
yield
console.log('a')
console.log('generator')
console.log('test')
}
const generator = testGenerator(); // Return the generator instance
generator.next();
// This
// is
Passing data to a generator
function* testGenerator() {
console.log('This')
console.log('is')
yield 10
yield 20
yield 30
console.log('a')
console.log('generator')
console.log('test')
}
const generator = testGenerator(); // Nothing here
// This is
console.log(generator.next()); // {value: 10, done: false}
console.log(generator.next()); // {value: 20, done: false}
console.log(generator.next()); // {value: 30, done: false}
// a
// generator
// test
console.log(generator.next()); // ?
console.log(generator.next()); // ?
This iterator object tells us two things:
- value: The data that was retrieved from within the generator function at the time when we yielded / exited.
- done: whether the generator function has finished it’s execution. In this example it has not because we would need to re-enter the generator with an additional .next() iterator call to continue, as we’ll see below.
Async Functions
const dataBase = {
id: 1,
name: 'Samuel',
lastName: 'Castro'
}
const findUser = () => {
console.log('Finding user');
return new Promise((resolve) => {
setTimeout(() => resolve(dataBase), 3000);
});
}
// Generator
const initUserGenerator = function*() {
const result = yield findUser()
return `User: ${result.name} ${result.lastName}`
}
const iterator = initUserGenerator(); // start out generator
const iteration = iterator.next(); // {value: Promise, done: false}
iteration.value.then(user => {
console.log(user); // {id: 1, name: "Samuel", lastName: "Castro"}
const nextIteration = iterator.next(user)
console.log(nextIteration); // {value: "User: Samuel Castro", done: true}
})
A more generic Async Generator
const dataBase = {
id: 1,
name: 'Samuel',
lastName: 'Castro'
}
const findUser = () => {
console.log('Finding user');
return new Promise((resolve) => {
setTimeout(() => resolve(dataBase), 3000);
});
}
function async(makeGenerator){
return function () {
var generator = makeGenerator.apply(this, arguments);
function handle(result){
// result => { done: [Boolean], value: [Object] }
if (result.done) return Promise.resolve(result.value);
return Promise.resolve(result.value).then(function (res){
return handle(generator.next(res));
}, function (err){
return handle(generator.throw(err));
});
}
try {
return handle(generator.next());
} catch (ex) {
return Promise.reject(ex);
}
}
}
const getUser = async(function* () {
const user = yield findUser() // Async operation in a sync way
console.log(`First Name: ${user.name}, LastName: ${user.lastName}`)
})
getUser() // First Name: Samuel, LastName: Castro
Async/Await (ES2017)
const dataBase = {
id: 1,
name: 'Samuel',
lastName: 'Castro'
}
const findUser = () => {
console.log('Finding user');
return new Promise((resolve) => {
setTimeout(() => resolve(dataBase), 3000);
});
}
const getUser = async () => {
const user = await findUser(); // Async operation in a awayc/await
console.log(`First Name: ${user.name}, LastName: ${user.lastName}`);
}
getUser() // First Name: Samuel, LastName: Castro
Questions
Generators
By Samuel Silva
Generators
- 104