generator詳解
阿新 • • 發佈:2017-10-22
直接 嵌套 遞歸 resolv typeof then n) else str
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傳給h2h1.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‘}); } //生成、... });
generator詳解