Asynchronous Generators

For all the asynchronous challenges that we face in our code, would be solved by either Async-Await or Promises. Here comes another powerful alternative module which we call them as Generators!!!

There is a mysterious secret behind these generators which I will reveal it in the final section of our blog.

Let’s define Generators in simple:

1. What are they?

They are generally function with a * notation

2. Why do we need them?

They are just like normal Javascript functions with the motive of pausing and resuming the required particular function executions, thereby achieving better execution control

Illustration:

   asyncGenerator(function* () {

     let promises=yield apiService.get("asyncDb/promises.json");

     console.log(promises);

     let callbacks=yield apiService.get("asyncDb/callbacks.json");

     console.log(callbacks);

     let asyncAwaits=yield apiService.get("asyncDb/asyncAwaits.json");

     console.log(asyncAwaits);

   })


   function asyncGenerator(generator){

     let a=generator();

     function handle(yieldObject){

       if(!yieldObject.done){

         yieldObject.value.then(function(data){

           return handle(a.next(data))

         })

       }

     }

     return handle(a.next());

   }

Illustration Explanation:

Here asyncGenerator is the generator. The keyword “yield” will pause the execution inside the function. Calling next() method each time will invoke the yield expressions separately one by one.

And most importantly the yield expression will return an object containing the keys value and done. The object is like,

{

value: {Promises…..} (the yielded return value will be here) 

done: false (states whether the generator execution have reached the end or not)

}

The above code looks almost the same as that of Async/await implementation. But what makes the difference is most important thing. Async/await returns a Promise, whereas Generators returns an object {value: X, done: Boolean}. Meanwhile yield returns a stream of values from the generators.

The error handling parts are very easier in generators when they are used along with RXJS filtering operators. Instead of using next() we could also use throw(error). Even we could force the generator to stop by using return() in place of next() methods.

When you are tired of using the next() method again and again, we could simplify it by using the setImmediate () method. This will make all the promises unwrap one by one and wait for them to resolve before calling the next iteration.

Example:  

“setImmediate(() => next())”

The mysterious secret will be revealed now. Do we really need to learn generators and use them in handy?

The answer is NOOOO!

generators

Because we have a more power tool “Async/await” which holds best due to its powerful features. Async/await is built using generators. Without these generators, Async/await will not work at all. But that doesn’t mean we do need to use and learn generators in our code. Generators are more complex. Let the framework and library developers use these generators to create more powerful modules like Async/await. The side benefit from the generator what we could say is “Easier Testing”. The famous bundler ”Brunch”, the interpreter “Co” and “Redux-Saga” make use of these generators specifically.

async-await

Reference Links: