Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Real world usage of two way generators in javascript

Tags:

javascript

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 }
like image 684
Rohit Sharma Avatar asked Dec 29 '15 02:12

Rohit Sharma


People also ask

What are JavaScript generators useful for?

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.

When should we use generators in ES6?

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.

What is unique about a generator function 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.

What are generator function in JavaScript How are they different from normal function?

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.


1 Answers

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!

like image 183
Xotic750 Avatar answered Oct 01 '22 08:10

Xotic750