1. 程式人生 > >generator詳解

generator詳解

直接 嵌套 遞歸 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傳給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‘});
  }

  //生成、...
});

generator詳解