Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

es6 Generator while(true)

Tags:

javascript

start to learning generator, i am encounter the following script.

I am confused by first next(), why the console.log is not printed for the very first next().

function* callee() {
    console.log('callee: ' + (yield));
}
function* caller() {
    while (true) {
        yield* callee();
    }
}

> let callerObj = caller();

> callerObj.next() // start
{ value: undefined, done: false } 
// why console.log is not returning 'callee' ??

> callerObj.next('a')
callee: a
{ value: undefined, done: false }

> callerObj.next('b')
callee: b
{ value: undefined, done: false }
like image 317
Bill Avatar asked Jul 22 '16 13:07

Bill


2 Answers

When you have a generator it starts in a suspended phase and the first next call runs the generator up to the first yield point. When you "yield from" a sub-generator, each time. If you add logging to the entry points of both your functions you will see this:

function* callee() {
  console.log('Callee is running up to the first yield point');
  console.log('callee: ' + (yield));
}
function* caller() {
  console.log('Caller is running up to the first yield point');
  while (true) {
    yield* callee();
  }
}

When you run this implementation using your test code you will see:

> let t = caller()
> t.next()
Caller is running up to the first yield point
Callee is running up to the first yield point
Object {value: undefined, done: false}
like image 156
Sean Vieira Avatar answered Sep 24 '22 02:09

Sean Vieira


When starting the generator (callerObj.next()), it always goes up to the first yield. Since you are delegating (yield *) to another generator, that yield would be the one in callee:

function* callee() {
    console.log('callee: ' + (yield));
                // this yield ^^^^^
}

Here the generator stops before executing console.log. If you were to yield a value back, this would be the return value of your first callerObj.next() call:

function* callee() {
    console.log('callee: ' + (yield 'value'));
}

The next callerObj.next('a') call will then replace the value at yield with 'a' and call console.log. In pseudo-code:

console.log('callee: ' + 'a');
// `yield` is replaced with 'a' for this invocation

It will then run until it encounters the same yield again (since you are in an infinite loop).

like image 37
nils Avatar answered Sep 26 '22 02:09

nils