Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this generator skip a yield outside the try block?

Background

I am experimenting with how Generator.prototype.throw() works and made this example:

var myGen = function *() {

    try{
        yield 1;
        yield 2;
        yield 3;
        yield 4;
        yield 5;
    }

    catch(err) {

        console.log(err);
    }

    yield 7;
    yield 8;
    yield 9;

}

var myIterator = myGen();

console.log(myIterator.next());
console.log(myIterator.next());
console.log(myIterator.next());

myIterator.throw(new Error('Bullocks!'));

console.log(myIterator.next());
console.log(myIterator.next());
console.log(myIterator.next());

which at runtime results in the following:

{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: false }
[Error: Bullocks!]
{ value: 8, done: false }
{ value: 9, done: false }
{ value: undefined, done: true }

Question

I can understand that yield 4 and the remaining part of the try block is skipped after throwing an error.

But why does the generator skip yield 7?

like image 724
rabbitco Avatar asked Apr 26 '16 06:04

rabbitco


1 Answers

It doesn't skip yield 7. When you call throw(), the control flow goes into the catch block, the error is logged, and then the execution continues until the next yield upon which a new iterator result object { value: 7, done: false } is returned.

It's just that in your code you don't console.log this one particular result object. Try:

console.log(myIterator.throw(new Error('Bullocks!')));

This is explained in step 11 and 13 of the spec:

  1. Resume the suspended evaluation of genContext using abruptCompletion as the result of the operation that suspended it. Let result be the completion record returned by the resumed computation.
  2. (…)
  3. Return Completion(result).
like image 104
Staś Małolepszy Avatar answered Sep 27 '22 22:09

Staś Małolepszy