JavaScript ES6 Generator Catch Error Before Next Method

Viewed 739

I start learn about Iterator/Generators and sometimes I saw some weird parts. Currently I don't understand why my code work like this.

In bellow code sample is my main code.

function* makeGenerator() {
    try {
        yield 1;
        yield 1;
        yield 1;
    } catch (e) {
        console.log(e);
    }
}

const generator = makeGenerator();

When I use next method before throw this code work normally.

console.log(generator.next()); // { done: false, value: 1 }
console.log(generator.throw("WTF?")); // "WTF"
console.log(generator.next()); // { done: true, value: undefined }

function* makeGenerator() {
  try {
    yield 1;
    yield 1;
    yield 1;
  } catch (e) {
    console.log(e);
  }
}

const generator = makeGenerator();

console.log(generator.next()); // { done: false, value: 1 }
console.log(generator.throw("WTF?")); // "WTF"
console.log(generator.next()); // { done: true, value: undefined }

But when I want to use throw method before next method I don't understand why next methods not work?

console.log(generator.throw("WTF?")); // "WTF"
console.log(generator.next());
console.log(generator.next());

function* makeGenerator() {
  try {
    yield 1;
    yield 1;
    yield 1;
  } catch (e) {
    console.log(e);
  }
}

const generator = makeGenerator();

console.log(generator.throw("WTF?")); // "WTF"
console.log(generator.next());
console.log(generator.next());

2 Answers

When this statement is executed:

const generator = makeGenerator();

...none of the code in the makeGenerator function body is executed yet, and so its try/catch block is not yet in effect. Only when you execute generator.next(), the code in the makeGenerator function body will start executing up until the next yield. At that point the try/catch block is in effect.

So... if you call generator.throw() before the first generator.next() call, you are triggering an exception that is not handled by the makeGenerator code. Your code breaks with an unhandled exception. As a consequence nothing that follows that generator.throw() (in your second code version) is executed.

The proper way of throwing errors via generators is to wrap them inside a try...catch because with not catching the error you're creating an error there, then, it falls through to the outer calling code (if any) and, if uncaught, kills the script.

function* makeGenerator() {
    try {
        yield 1;
        yield 1;
        yield 1;
    } catch (e) {
        console.log(e);
    }
}

const generator = makeGenerator();
console.log(generator.next()); 
try {
  generator.throw(new Error("WHOOPS"));
} catch(e) {
  console.log(e); // shows the error
}
Related