/** * Execute the generator function or a generator * and return a promise. * * @param {Function} fn * @return {Promise} * @apipublic */
functionco(gen) { var ctx = this; var args = slice.call(arguments, 1);
// we wrap everything in a promise to avoid promise chaining, // which leads to memory leak errors. // see https://github.com/tj/co/issues/180 returnnewPromise(function (resolve, reject) { // 启动generator函数。 if (typeof gen === 'function') gen = gen.apply(ctx, args); // 如果gen不存在或者gen.next不是函数(非generator函数)则返回空值 if (!gen || typeof gen.next !== 'function') returnresolve(gen);
functionco(gen) { if (typeof gen === 'function') gen = gen.apply(ctx, args); onFulfilled();
functiononFulfilled(res) { var ret; try { ret = gen.next(res); } catch (e) { returnreject(e); } next(ret); } functionnext(ret) { if (ret.done) returnresolve(ret.value); var value = toPromise.call(ctx, ret.value); if (value && isPromise(value)) return value.then(onFulfilled, onRejected); returnonRejected( newTypeError( 'You may only yield a function, promise, generator, array, or object, ' + 'but the following object was passed: "' + String(ret.value) + '"' ) ); } }
这儿,在给 co 传入一个generator函数后,co 会将其自动启动。然后调用onFulfilled函数。 在onFulfilled函数内部,首先则是获取 next 的返回值。交由next函数处理。 而next函数则首先判断是否完成,如果这个 generator 函数完成了,返回最终的值。 否则则将yield后的值,转换为Promise。 最后,通过Promise的 then,并将onFulfilled函数作为参数传入。
1 2 3
if (value && isPromise(value)) { return value.then(onFulfilled, onRejected); }
而在generator中,yield句本身没有返回值,或者说总是返回undefined。 而 next 方法可以带一个参数,该参数就会被当作上一个yield语句的返回值。 同时通过onFulfilled函数,则可以实现自动调用。 这也就能解释为什么 co 基于Promise。且能自动执行了。