簡體   English   中英

Javascript奇怪的生成器產生子函數行為

[英]Javascript strange generator yield sub function behavior

我在一個簡單的項目中使用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函數上嘗試了很多不同的東西,有或沒有屈服。

這是怎么回事?

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);
}

這個更簡單的版本可能有助於yieldyield*之間的差異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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM