[英]Javascript strange generator yield sub function behavior
我在一個簡單的項目中使用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函數上嘗試了很多不同的東西,有或沒有屈服。
這是怎么回事?
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);
}
yield subtest1(conn, values)
調用subtest1(conn, values)
,它返回一個迭代器對象,然后從test1
得到它作為test1
迭代的值。 它不會迭代 subtest1
迭代器返回的值。
你可以讓test1
通過在yield
之后添加*
迭代來自subtest1
的迭代器的值:
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*
之間的差異yield*
:
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);
}
輸出結果是:( Babel的REPL上的實時拷貝 )
f {} f done
注意我們根本看不到任何“b”記錄; 那是因為你在f1
之后看到的{}
是調用bar
返回的迭代器對象。
如果我們只在yield bar();
上添加*
yield bar();
行,把它變成yield* bar()
,輸出改變:(實時拷貝)
f b1 b2 0 b2 1 b2 2 b done f done
如果yield*
的操作數是迭代器,則yield*
迭代它, yield
每個值。 它基本上是:
for (value of bar()) {
yield value;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.