function*
generators
Description
Generators are functions which can be exited and later re-entered. Their context (variable bindings) will be saved across re-entrances.
Generators in JavaScript -- especially when combined with Promises -- are a very powerful tool for asynchronous programming as they mitigate -- if not entirely eliminate -- the problems with callbacks, such as Callback Hell and Inversion of Control. However, an even simpler solution to these problems can be achieved with async functions.
Declaration
function* generator(i) {
yield i;
yield i + 10;
}
const gen = generator(10);
console.log(gen.next().value);
// expected output: 10
console.log(gen.next().value);
// expected output: 20
Methods
Also inherits methods from: Iterator
Generator.prototype.next()
Returns a value yielded by the yield expression.
Generator.prototype.return()
Returns the given value and finishes the generator.
Generator.prototype.throw()
Throws an error to a generator (also finishes the generator, unless caught from within that generator).
function* generateSequence() {
yield 1;
yield 2;
return 3;
}
const generator = generateSequence();
for(let value of generator) {
console.log(value); // 1, then 2
}
...
function* generateSequence() {
yield 1;
yield 2;
yield 3;
}
const sequence = [0, ...generateSequence()];
console.log(sequence); // 0, 1, 2, 3
Iterator
const range = {
from: 1,
to: 5,
[Symbol.iterator]() {
return this;
},
next() {
if (this.current === undefined) {
this.current = this.from;
}
if (this.current <= this.to) {
return {
done: false,
value: this.current++
};
} else {
delete this.current;
return {
done: true
};
}
}
};
for (const num of range) {
console.log(num); // 1, 2, 3, 4, 5
}
console.log(Math.max(...range)); // 5
Generator
const range = {
from: 1,
to: 5,
*[Symbol.iterator]() { // a shorthand for [Symbol.iterator]: function*()
for(let value = this.from; value <= this.to; value++) {
yield value;
}
}
};
console.log( [...range] ); // 1,2,3,4,5
// генератор для получения и показа аватара, он yield'ит промисы
function* showUserAvatar() {
let userFetch = yield fetch('/article/generator/user.json');
let userInfo = yield userFetch.json();
let githubFetch = yield fetch(`https://api.github.com/users/${userInfo.name}`);
let githubUserInfo = yield githubFetch.json();
let img = new Image();
img.src = githubUserInfo.avatar_url;
img.className = "promise-avatar-example";
document.body.appendChild(img);
yield new Promise(resolve => setTimeout(resolve, 3000));
img.remove();
return img.src;
}
// вспомогательная функция-чернорабочий для выполнения промисов из generator
function execute(generator, yieldValue) {
let next = generator.next(yieldValue);
if (!next.done) {
next.value.then(
result => execute(generator, result),
err => generator.throw(err)
);
} else {
// обработаем результат return из генератора обычно здесь вызов callback или что-то в этом духе
console.log(next.value);
}
}
execute( showUserAvatar() );
Browser compatibility
Generators
By Andrew Bogomolov
Generators
- 49