generator详解

generator函数

yield可以返回值,也可以传入值

形式:

注意!generator不能写成arrow function的形式!!!

function *函数(){
    代码1...

    let a = yield b; //b可以返回去给c

    代码2...
}
let Obj
=函数();

let c = Obj.next();
//执行代码1
genObj.next(5); //执行代码2 这里的5可以传入给a

 generator是一个异步串行的神器!!!

最传统的异步串行在前面的文章也介绍过,就是不断的嵌套回调函数,非常恶心。

用promise来写异步串行也是如此!!promise更适用与“异步并行”,即等齐所有异步结果再执行代码。

而今天的主角generator就很强势,直接可以把异步写成同步的写法~~

function *函数(){
    代码1...

    let a = yield b; //b假设是一个promise
    
    if(a == '~~~'){
       let c = yield d; //d假设是一个promise
    }else{
        let e = yield f;//f假设是一个promise
    }
    代码2...
}

let g = 函数();

//h1接收第一个promise let h1
= g.next().value; let h2; //promise异步得到的数据传回给上面的a,把下一个promise传给h2 h1.then(res=>{h2 = g.next(res).value},err=>console.log(err)); h2.then(res=>g.next(res),err=>console.log(err));

当然上面这样写不太简洁,后面还要自己手动去next,把promise的结果传回去

我们可以考虑自己封装一个函数,采用递归的方式来自动实现下面的“next”的书写

runner

//这个runner是个函数,参数是一个generator函数
function runner(_gen){
  return new Promise((resolve, reject)=>{
    var gen=_gen();

    _next();
    //runner函数里面封装一个_next()函数用于递归
    function _next(_last_res){
      //首先res获取next得到的yield的返回值
      var res=gen.next(_last_res);
      //如果generator没有走完
      if(!res.done){
        var obj=res.value;
        //如果返回的是promise
        if(obj.then){
          //等promise返回数据 递归自己 next(res) 传入promise得到的数据
          obj.then((res)=>{
            _next(res);
          }, (err)=>{
            reject(err);
          });
        }
        //若返回的是generator
        else if(typeof obj=='function'){
          if(obj.constructor.toString().startsWith('function GeneratorFunction()')){
            runner(obj).then(res=>_next(res), reject);
          }
          //obj是一个普通函数,就会传这个函数return的值
          else{
            _next(obj());
          }
        }else{
          _next(obj);
        }
      }else{
        resolve(res.value);
      }
    }
  });
}
    

这样,以后写的代码就变得很简洁了!!

runner(function *(){
  let userData=yield $.ajax({url: 'getUserData', dataType: 'json'});

  if(userData.type=='VIP'){
    let items=yield $.ajax({url: 'getVIPItems', dataType: 'json'});
  }else{
    let items=yield $.ajax({url: 'getItems', dataType: 'json'});
  }

  //生成、...
});
原文地址:https://www.cnblogs.com/amiezhang/p/7707523.html