Coming from C# world, I am curious to understand what are some of the practical usage of two way generators in javascript. I can understand how generators can be useful in general, but not when it comes to two way generators. Can we use it with RxJS or likes? Can you explain any pattern/scenario where this can be used?
function* interrogate() {
let name = yield "What is your name?";
let color = yield "What is your favorite color?";
return `${name}'s favorite color is ${color}.`;
}
let it = interrogate();
it.next(); // { value: "What is your name?", done: false }
it.next('Ethan'); // { value: "What is your favorite color?", done: false }
it.next('orange'); // { value: "Ethan's favorite color is orange.", done:true }
Generator functions provide a powerful alternative: they allow you to define an iterative algorithm by writing a single function whose execution is not continuous. Generator functions are written using the function* syntax. When called, generator functions do not initially execute their code.
In a normal function, there is only one entry point: the invocation of the function itself. A generator allows you to pause the execution of a function and resume it later. Generators are useful when dealing with iterators and can simplify the asynchronous nature of Javascript.
Generators are a special class of functions that simplify the task of writing iterators. A generator is a function that produces a sequence of results instead of a single value, i.e you generate a series of values.
The difference between a generator and a regular function is: In response to a generator call, its code doesn't run. In its place, it returns a special object called a 'Generator Object' to manage the execution. At any time, the generator function can return (or yield) the control back to the caller.
David Walsh has a blog about ES6 Generators
He has an example
function *foo(x) {
var y = 2 * (yield (x + 1));
var z = yield (y / 3);
return (x + y + z);
}
var it = foo( 5 );
// note: not sending anything into `next()` here
console.log( it.next() ); // { value:6, done:false }
console.log( it.next( 12 ) ); // { value:8, done:false }
console.log( it.next( 13 ) ); // { value:42, done:true }
But again, the use case is as manufactured as your example.
In his summary he says
It's natural to wonder what this new exotic toy is going to do practically for your code. There's a lot more to them, though. We've just scratched the surface. So we have to dive deeper before we can discover just how powerful they can/will be.
- How does error handling work?
- Can one generator call another generator?
- How does async coding work with generators?
Those questions, and more, will be covered in subsequent articles here, so stay tuned!
In a later blog he has the following snippet (and some others)
// run (async) a generator to completion
// Note: simplified approach: no error handling here
function runGenerator(g) {
var it = g(), ret;
// asynchronously iterate over generator
(function iterate(val){
ret = it.next( val );
if (!ret.done) {
// poor man's "is it a promise?" test
if ("then" in ret.value) {
// wait on the promise
ret.value.then( iterate );
}
// immediate value: just send right back in
else {
// avoid synchronous recursion
setTimeout( function(){
iterate( ret.value );
}, 0 );
}
}
})();
}
runGenerator( function *main(){
var result1 = yield request( "http://some.url.1" );
var data = JSON.parse( result1 );
var result2 = yield request( "http://some.url.2?id=" + data.id );
var resp = JSON.parse( result2 );
console.log( "The value you asked for: " + resp.value );
} );
Which seems a bit more real world.
He summarises
Put simply: a generator + yielded promise(s) combines the best of both worlds to get really powerful and elegant sync(-looking) async flow control expression capabilities. With simple wrapper utilities (which many libraries are already providing), we can automatically run our generators to completion, including sane and sync(-looking) error handling!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With