异步操作——generator

reference

  1. https://www.cnblogs.com/chenjinxinlove/p/8467774.html
  2. https://juejin.im/post/5b54ca8ef265da0f7e628b6f
  3. https://juejin.im/post/5a30193051882503dc53af3c#heading-13
  4. https://juejin.im/post/5bcf3e3f6fb9a05cd53b3e3d#heading-11

1. 深入理解异步操作

“认识generator”这篇文章中,我更多地是从迭代器的角度去看generator,我们现在从异步操作的角度来看待generator

function* gererator(){
  //do some stuff
  yield value1;
 //do some stuff;
  yield value2;
}

执行权一直calling codegenerator函数两个地方轮换,两段代码的数据交流可以通过yield.next(data)进行交换。
generator异步读取文件的实例

var fs=require('fs');
var readfile=function(filename){
  return new Promise((resolve,reject=>{
    fs.readFile(filename, (error,data)=>{
        if(error) reject(new Error('whoops');
        resolve(data);
      });
  });
}
//generator
var gen=function* (){
  var file1=yield readfile('./data1.json');
  var file2= yield readfile('./data2.json');
  console.log('done');
}
//calling code
var generator=gen();
generator.next().value.then(data=>{
  generator.next(data).value.then((data)=>{
      generator.next(data);
    }
  );
});

在外层的calling code部分,我们可以用自动执行器,来让generator函数执行,比如我们可以引入模块co来完成上述calling code的操作。
也可以自己写一个自动执行器

function run(generator){
    var g=generator();
    function next(data){
        var result=g.next(data);
        if(result.done){
            console.log(result.value);
        }else{
            result.value.then(function(data){
                next(data);
            });
        }
    }
    next();
}

事实上,上述代码如果asyncawait的语法来写,就会变得非常简洁。

async function loadFile(){
  var file1=await readfile('./data1.json');
  var file2=await readfile('/data2.json');
  console.log('done');
}

2. async函数的实现原理, 就是将Generator 函数和自动执行器, 包装在一个函数里。

function getName(name){
    return new Promise((resolve)=>{
        setTimeout(resolve(name),1000);
    });
}
function* gen(){
    let data1=yield getName('nancy');
    let data2=yield getName('bill');
    return [data1,data2];
}
function run(generator){
    return new Promise(resolve=>{
        var g=generator();
        var output;
        function next(data){
            var result=g.next(data);
            if(result.done){
                output=result.value;
                resolve(output);
            }else{
                result.value.then(function(data){
                    next(data);
                });
            }
        }
        next();
    });
}
run(gen).then(console.log); //output ['nancy','bill'].
//example:
// var fs=require('fs');
function getName(name)
{
    return new Promise(resolve=>{
        setTimeout(resolve(name),1000);
    });
}
async function readfile(name1,name2){
    let data1=await getName(`hello, ${name1}`);
    let data2=await getName(`hello, ${name2}`);
    return [data1,data2];
}
// now use promise and generator.
function* generator(name1,name2){
    let data1=yield getName(`hello, ${name1}`);
    let data2=yield getName(`hello, ${name2}`);
    return [data1,data2];
}
function wrapper(gen){
    return function(...args){
        return new Promise(resolve=>{
            var g=gen(...args);
            function next(data){
                var result=g.next(data);
                if(result.done) resolve(result.value)
                else{
                    result.value.then(data=>{
                        next(data);
                    });
                }
            }
            next();
        });
    }
}
var readfile_gen=wrapper(generator);
readfile('jason','gisele').then(console.log);
readfile_gen('jason','gisele').then(console.log);

包装函数:

const wrapAsync=function(generatorFn){
  return function(...args){
    return new Promise(resolve=>{
      var g=generatorFn(...args);
      function next(data){
        var result=g.next(data);
        if(result.done) resolve(result.value);
        else{
          result.value.then(data=>{
            next(data);
          });
        }
      }
      next();
    });
  }
}

你可能感兴趣的:(异步操作——generator)