/***为方便提取slice()函数*/varslice=Array.prototype.slice;/***公开`co`。*/module.exports=co['default']=co.co=co;/***包装生成器函数`fn`并返回一个承诺*这是一个单独的函数,因此*每个`co()`调用都不会创建一个新的,*不必要的闭包。**@param{GeneratorFunction}fn*@return{Function}*@apipublic*/co.wrap=function(fn){createPromise.__generatorFunction__=fn;返回创建承诺;functioncreatePromise(){returnco.call(this,fn.apply(this,arguments));}};/***执行不带参数的生成器函数并返回promise**@param{Function}fn*@return{Promise}*@apipublic*/functionco(gen){varctx=this;varargs=slice.call(arguments,1);//我们将所有内容都包装在一个promise中以避免promise链接,//这会导致内存泄漏错误。//见https://github.com/tj/co/issues/180returnnewPromise(function(resolve,reject){//如果是函数,直接执行,apply指定作用域if(typeofgen==='函数')gen=gen.apply(ctx,args);//判断相当于!(gen&&typeofgen.next==='function'),判断生成器函数是否已经执行(根据返回值是否为Iterator对象),执行完通过resolve返回,外部将执行`。then`functionif(!gen||typeofgen.next!=='function')returnresolve(gen);onFulfilled();/***.next带参数用于修改最后的yield结果,V8引擎会忽略第一个执行参数*try/catch用于捕获错误*执行后的结果交给自定义的next函数,res结构应该是{value,done}*/functiononFulfilled(res){varret;试试{ret=gen.next(res);}catch(e){返回拒绝(e);}下一个(退);返回空值;/***自己catcherr*注意这里是调用生成器遍历器的throw方法*生成器发生错误后不会执行,返回{value:undefined,done:true},所以这里调用next函数将在第一个if*/functiononRejected(err){varret;试试{ret=gen.throw(err);}catch(e){返回拒绝(e);}下一个(退);}/***首先检查是否结束*如果没有结束,将结果值转换成Promise类型*如果转换成功则执行Promise,这里是通过onFulfilled调用的,现在依次调用onFulfilled,形成递归。*失败时调用onRejected函数*/functionnext(ret){if(ret.done)returnresolve(ret.value);varvalue=toPromise.call(ctx,ret.value);if(value&&isPromise(value))returnvalue.then(onFulfilled,onRejected);returnonRejected(newTypeError('你只能产生一个函数、promise、生成器、数组或对象,'+'但传递了以下对象:"'+String(ret.value)+'"'));}});}/***将`yield`ed值转换为promise。**@param{Mixed}obj*@return{Promise}*@apiprivate*/functiontoPromise(obj){if(!obj)returnobj;如果(isPromise(obj))返回obj;如果(isGeneratorFunction(obj)||isGenerator(obj))returnco.call(this,obj);if('function'==typeofobj)returnthunkToPromise.call(this,obj);如果(Array.isArray(obj))返回arrayToPromise.call(this,obj);如果(isObject(obj))返回objectToPromise.call(this,obj);returnobj;}/***将thunk转换为promise。**@param{函数}*@return{Promise}*@apiprivate*/functionthunkToPromise(fn){varctx=this;returnnewPromise(function(resolve,reject){fn.call(ctx,function(err,res){if(err)returnreject(err);if(arguments.length>2)res=slice.call(arguments,1);resolve(res);});});}/***将“yieldables”数组转换为promise。*在内部使用`Promise.all()`。**@param{Array}obj*@return{Promise}*@apiprivate*/functionarrayToPromise(obj){returnPromise.all(obj.map(toPromise,this));}/***转换一个对象承诺的“收益”。*在内部使用`Promise.all()`。**@param{Object}obj*@return{Promise}*@apiprivate*/functionobjectToPromise(obj){varresults=newobj.constructor();varkeys=Object.keys(obj);var承诺=[];for(vari=0;i
