实现一个极简版的co
thunk版本
function* gen1(){ yield req('1') yield req('2'); yield req('3'); } co(gen1)(); function req(a){ return function(cb){ setTimeout(() => { console.log('req: ',a,new Date()); cb && cb(); },a*1000); } } function co(genFun){ return function(done){ let gen = genFun(); next(); function next(err,res){ if(err){ return done && done(err); } let ret = gen.next(res); if(ret.done){ done && done(); } else{ ret.value(next); } } } }
promise版本
function createPromise(n,type){ console.log('create promise: ', n); return Promise[type](n); } function* gen2(){ yield createPromise(1,'resolve'); yield createPromise(2,'resolve'); yield createPromise(3,'reject'); yield createPromise(4,'resolve'); } co(gen2).then(res => console.log(res)).catch(err => console.log(err)); function co(genFun){ return new Promise((resolve,reject) => { let g = genFun(); onResolve(); function onResolve(res){ try{ ret = g.next(res); } catch(e){ return reject(e); } next(ret); } function onReject(err){ try{ ret = g.throw(err); } catch(e){ return reject(e); } next(ret); } function next(ret){ if(ret.done) return resolve(ret.value); if(isPromise(ret.value)){ return ret.value.then(onResolve,onReject) } return onReject(new TypeError('yield params is not supported')) } }) } function isPromise(obj){ return obj && typeof obj.then === 'function'; }