Javascript奇怪的生成器产生子函数行为

时间:2015-12-13 16:35:22

标签: javascript mysql generator ecmascript-6 yield

我在一个简单的项目中使用MySQL(mysql-co)和ASQ(asynquence)来更好地理解ES6生成器和yield函数,我对一个奇怪的行为感到难过。

asynquence

的简短说明

asynquencehttps://github.com/getify/asynquence)为我提供了一种简单的方法来按顺序运行生成器。它也可以执行伪并行执行,但这不是我现在所需要的。 function *x(token)的结构就是从那里开始的。 token[0]拥有一个连接对象。 yield token按顺序将控制权传递给下一个生成器函数。

代码示例1(正常)

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驱动程序允许这样一个简单的插入函数,但确实如此。

代码示例2(不起作用)

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函数上尝试了很多不同的东西。

发生了什么事?

2 个答案:

答案 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