我在一个简单的项目中使用MySQL(mysql-co
)和ASQ(asynquence
)来更好地理解ES6生成器和yield函数,我对一个奇怪的行为感到难过。
asynquence
asynquence
(https://github.com/getify/asynquence)为我提供了一种简单的方法来按顺序运行生成器。它也可以执行伪并行执行,但这不是我现在所需要的。 function *x(token)
的结构就是从那里开始的。 token
在[0]
拥有一个连接对象。 yield token
按顺序将控制权传递给下一个生成器函数。
function *test1(token) {
var conn = token.messages[0];
var values = {id:1, dev:1, description:'This is it!'};
yield conn.query("INSERT INTO version SET ?", values);
yield token;
}
这很好用。插入上述行。我不知道MySQL驱动程序允许这样一个简单的插入函数,但确实如此。
function *test1(token) {
var conn = token.messages[0];
var values = {id:1, dev:1, description:'This is it!'};
yield subtest1(conn, values);
yield token;
}
function *subtest1(conn, values) {
yield conn.query("INSERT INTO version SET ?", values);
}
这不起作用。 subtest1的实际代码是在模型类中,所以我不希望它与控制器合并。
我在subtest函数上尝试了很多不同的东西。
发生了什么事?
答案 0 :(得分:3)
subtest1(conn, values)
是一个生成器。 yield
生成器对象不会执行它的主体。也就是说,生成的生成器保持挂起状态,并且需要调用next()
方法才能到达第一个yield
。 代码示例2 中没有对next()
的显式或隐式调用,这就是conn.query(...)
未执行的原因。
yield* subtest1(conn, values)
怎么样?从链接页面:
yield*
表达式遍历操作数并产生每个值 由它返回。
它仍会懒散地执行subtest
。
另一种解决方案是将subtest
转换为常规函数并返回conn.query(...)
的结果(假设您只需要执行一个查询):
function subtest1(conn, values) {
return conn.query("INSERT INTO version SET ?", values);
}
答案 1 :(得分:3)
yield subtest1(conn, values)
调用subtest1(conn, values)
,它返回一个迭代器对象,然后从test1
得到该值作为test1
迭代的值。它不会迭代 subtest1
迭代器返回的值。
你 可以<{1}}通过在test1
之后添加subtest1
来迭代*
迭代器中的值/ p>
yield
但是看着你的代码,我不认为你想要。如果要将yield* subtest1(conn, values);
行拆分为函数,它将如下所示:
conn.query
这个更简单的版本可能有助于function *test1(token) {
var conn = token.messages[0];
var values = {id:1, dev:1, description:'This is it!'};
yield subtest1(conn, values);
yield token;
}
function subtest1(conn, values) {
return conn.query("INSERT INTO version SET ?", values);
}
和yield
之间的差异:
yield*
输出是:(live copy on Babel's REPL)
f {} f done
请注意我们没有看到任何&#34; b&#34;完全记录;那是因为你在function* foo() {
console.log("f");
yield bar();
console.log("f done");
}
function* bar() {
console.log("b1");
let i = 0;
while (i < 3) {
console.log("b2");
yield i;
++i;
}
console.log("b done");
}
for (let v of foo()) {
console.log(v);
}
之后看到的{}
是通过调用f1
返回的迭代器对象。
如果我们只在bar
行添加*
,将其转为yield bar();
,则输出会更改:(实时复制)
f b1 b2 0 b2 1 b2 2 b done f done
如果yield* bar()
的操作数是迭代器,yield*
将迭代它,yield*
其每个值。它基本上是:
yield