看起来,yield 是语法糖,用于将返回的内容包装在回调中并适当地分配结果值(至少在 co 的情况下,将错误参数扔给回调)
不,yield
不是语法糖。它是生成器的核心语法元素。当该生成器被实例化时,您可以运行它(通过调用.next()
它),这将返回被return
ed 或yield
ed 的值。当生成器被yield
编辑后,您可以稍后通过.next()
再次调用来继续它。to 的参数next
将是表达式yield
在生成器内返回的值。
只有在这种情况下co
,那些异步回调的事情(和其他事情)才会“适当地”处理,因为您认为在异步控制流库中是自然的。
当使用 yield 时,done 是什么样子的?
您阅读的文章中的thread
函数示例给您一个很好的印象:
function thread(fn) {
var gen = fn();
function next(err, res) {
var ret = gen.next(res);
if (ret.done) return;
ret.value(next);
}
next();
}
在您的代码中,运行生成器时确实会从生成器中生成yield
表达式的值。read("file")
这成为ret.val
的结果gen.next()
。为此,next
传递了函数 - 一个回调,它将使用res
传递给它的 ult 继续生成器。在您的生成器代码中,看起来好像yield
表达式返回了这个值。
发生的事情的“展开”版本可以这样写:
function fn*() {
console.log( yield function (done) {
fs.readFile("filepath", "file", done);
} );
}
var gen = fn();
var ret1 = gen.next();
var callasync = ret1.value;
callasync(function next(err, res) {
var ret2 = gen.next(res); // this now does log the value
ret2.done; // true now
});