📜 ⬆️ ⬇️

My favorite feature of generators

Already on Habré they wrote about how new generators work and I will not even be the first to write about their ability to suspend their execution with the yield instruction.

After reading the article "Generators in node.js (a new way of dealing with noodles)", the idea that you can do without noodles-callBacks did not leave me, but I could not accept the fact that for every asynchronous function that we want to call, we need to write a wrapper function.

And then the idea was born! Very simple, but its essence is that inside the generator there is a link to the function n , which we pass to asynchronous functions as callBack, suspend the generator with the help of yield, and then our function n continues the execution of the generator, passing to it an array formed from the arguments, with whom she was called.
')
Interested please under the cat.

How does it look in practice?


And so: there is a function Sync, which, in fact, makes such shamanism possible. It creates the function n , then initializes the generator, passing this function to it and starts the whole thing.

Sync=function(fn) { var gen; var callBack=function() { gen.next(Array.prototype.slice.call(arguments,0)); }; gen=fn(callBack); gen.next(); }; 


And now the fun part!

 var fs=require('fs'); //  FS console.log(1); //   1 Sync(function*(cb) { //   Sync -   ,  callBack    console.log(2); //   2 yield fs.readFile('sync.js','utf-8',cb); //        callBack,      console.log(4); //   4 }); console.log(3); //   3 


In the output we will see:
one
2
3
four

4 is output after 3 because with the help of the yield construction we interrupted the work of the generator function,
and then the readFile asynchronous function terminated and called the callBack, which we passed to it,
which in turn continued the execution of the generator function.

So you can see that after the first suspension our generator immediately becomes a separate stream, which is very important to remember. In this way, it is impossible to suspend the current thread just because you wanted to use asynchronous functions synchronously. This is only a method of dealing with noodles, nothing more.

And now the most delicious: return the results!

 var fs=require('fs'); Sync(function*(cb) { var result=yield fs.readFile('sync.js','utf-8',cb); console.log(result[1]); }); 


Everyone remembers that readFile passes 2 arguments to callBack:
  1. Error message if it happened
  2. Data from file


That is why we turned to the second element of the array.

Simple and elegant in my opinion. It remains to wait until the generators come out in stable nodejs assemblies and browsers.

Source: https://habr.com/ru/post/228363/


All Articles