标签:ack 手动 user col 函数 else ring 封装 res
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‘}); } //生成、... });
标签:ack 手动 user col 函数 else ring 封装 res
原文地址:http://www.cnblogs.com/amiezhang/p/7707523.html