Skip to content Skip to sidebar Skip to footer

Javascript Strange Generator Yield Sub Function Behavior

I'm using MySQL (mysql-co) and ASQ(asynquence) in a simple project to get a better understanding of ES6 generators and yield functions, and I'm stumped on an odd behavior. Short ex

Solution 1:

subtest1(conn, values) is a generator. yielding a generator object does not execute its body. That is, the yielded generator remains suspended, and it would require a call to the next() method for the first yield to be reached. There are no explicit or implicit calls to next() in Code Sample 2, and this is the reason conn.query(...) isn't executed.

How about yield* subtest1(conn, values)? From the linked page:

The yield* expression iterates over the operand and yields each value returned by it.

It will still execute subtest lazily.

An alternative solution is to turn subtest into a regular function and return the result of conn.query(...) (assuming you only need to perform one query):

functionsubtest1(conn, values) {
    return conn.query("INSERT INTO version SET ?", values);
}

Solution 2:

yield subtest1(conn, values) calls subtest1(conn, values), which returns an iterator object, and then yields that from test1 as the value for that iteration of test1. It doesn't iterate the values returned by the subtest1 iterator.

You could have test1 iterate the values from subtest1's iterator by adding a * after the yield:

yield* subtest1(conn, values);

but looking at your code, I don't think you want to. If you want to split the conn.query line out into a function, it would look like this:

function *test1(token) {
  var conn = token.messages[0];
  var values = {id:1, dev:1, description:'This is it!'};
  yieldsubtest1(conn, values);
  yield token;
}
functionsubtest1(conn, values) {
  return conn.query("INSERT INTO version SET ?", values);
}

This simpler version may help with the difference between yield and yield*:

function* foo() {
  console.log("f");
  yieldbar();
  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 offoo()) {
  console.log(v);
}

The output of that is: (live copy on Babel's REPL)

f
{}
f done

Note how we don't see any of the "b" logging at all; that's because the {} you see after f1 is the iterator object returned by calling bar.

If we just add * on the yield bar(); line, turning it into yield* bar(), the output changes: (live copy)

f
b1
b2
0
b2
1
b2
2
b done
f done

If the operand to yield* is an iterator, yield* iterates it, yielding each of its values. It's basically:

for (value of bar()) {
    yieldvalue;
}

Post a Comment for "Javascript Strange Generator Yield Sub Function Behavior"