Generator functions
Create Generator functions
Consume data from Generator functions
Other ways to create Generator functions
4.1. Generator function with function expression
4.2. Generator function with object literal
4.3. Generator function with class syntax
Passing parameter to Generator function via next()
yield*
Async Generator
Generators are function definition that lazly, on demand returns synchronous iteratables.
Generator functions are written using the function* syntax.
NOTE: Arrow function syntax can't be used with generator function. The function* statement defines a generator function.
function* getSyncData(){
yield 1; // we can call any functions here
yield 2;
yield 3;
}
//Option 1: Using JS destructuring
const [a, b, c] = getSyncData();
console.log(`a - ${a}, b - ${b}, c - ${c}`);
//Output
a - 1, b - 2, c - 3
//Option 2: Using spread operator
console.log(`${[...getSyncData()]}`);
//Output
1,2,3
//Option 3: Using array.from function
console.log(`${Array.from(getSyncData())}`);
console.log(`${Array.from(getSyncData(), x=> x*x)}`);
//Output
1,2,3
1,4,9
//Option 4: Using for...of loop
for(const x of getSyncData()){
console.log(x);
}
//Output
1
2
3
//Option 5: Using next() function
const iteratable = getSyncData();
console.log(iteratable.next());
console.log(iteratable.next());
console.log(iteratable.next());
console.log(iteratable.next());
//Output
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
{ value: undefined, done: true }
yield
does two thing:
next()
like return
.yield
on invocation of next()
.When all the values has been exhausted, yield
returns ```{value: undefined, done: true}``
const getSyncData = function* (){
yield 1;
yield 2;
yield 3;
}
const obj = {
*getSyncData(){
yield 'a';
yield 'b';
yield 'c';
}
}
//Above object literal syntax is similar to
var obj = {
getSyncData: function* () {
yield 'a';
yield 'b';
yield 'c';
}
}
const [a, b, c] = obj.getSyncData();
console.log(`a -> ${a}, b -> ${b}, c -> ${c}`);
//Output
a -> a, b -> b, c -> c
class MyClass{
* getSyncData(){
yield 'a';
yield 'b';
yield 'c';
}
}
const obj = new MyClass();
const [a, b, c] = obj.getSyncData();
console.log(`a -> ${a}, b -> ${b}, c -> ${c}`);
//Output
a -> a, b -> b, c -> c
//Option 1
class MyClass{
* getSyncData(list, index){
console.log(`list ${list}`);
console.log(`index ${index}`);
}
}
const obj = new MyClass();
const [a, b] = obj.getSyncData([1,2], 1);
//Output
list 1,2
index 1
//Option 2
function* getSyncData(){
const value = yield;
console.log(`Value ${value}`);
}
const gen = getSyncData();
gen.next(3); // first value will be lost
gen.next(4); // Will pass only once
gen.next(5); // this value will also lost
//Output
Value 4
yield*
helps delegate to another generator function or iterator.
We can use yield*
inside any generator function or with iterator and call another generator function.
function* getSyncData(){
yield 1;
yield 2;
yield 3;
}
function* getData(){
yield 'a';
yield getSyncData();
yield 'b'
}
const iteratable = getData();
console.log(iteratable.next());
console.log(iteratable.next());
console.log(iteratable.next());
console.log(iteratable.next());
console.log(iteratable.next());
//Output
{ value: 'a', done: false }
{ value: Object [Generator] {}, done: false }
{ value: 'b', done: false }
{ value: undefined, done: true }
{ value: undefined, done: true }
Now let's replace yield with yield* in getData()
function.
function* getData(){
yield 'a';
yield* getSyncData();
yield 'b'
}
const iteratable = getData();
console.log(iteratable.next());
console.log(iteratable.next());
console.log(iteratable.next());
console.log(iteratable.next());
console.log(iteratable.next());
//Output
{ value: 'a', done: false }
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
{ value: 'b', done: false }
Generators can be used as async methods as well.
async function* getSyncData() {
yield await Promise.resolve('a');
yield await Promise.resolve('b');
yield await Promise.resolve('c');
}
let str = '';
async function consumeGenerator() {
for await (const val of getSyncData()) {
str = str + val;
}
console.log(str);
}
consumeGenerator();
//Output
abc
Note: async generators, the generator.next() method is asynchronous, it returns promises. In a regular generator we’d use result = generator.next() to get values. In an async generator, we should add await.