javascripttypescriptiteratorgeneratorasync-iterator

How can I find out if a javascript iterator terminates early?


Lets say I have a generator:

function* source() {
  yield "hello"; yield "world";
}

I create the iterable, iterate with a for-loop, and then break out of the loop before the iterator fully completes (returns done).

function run() {
  for (let item of source()) {
    console.log(item);
    break;
  }
}

Question: How can I find out, from the iterable-side, that the iterator terminated early?

There doesn't seem to be any feedback if you try to do this directly in the generator itself:

function* source2() {
  try {
    let result = yield "hello";
    console.log("foo");
  } catch (err) {
    console.log("bar");
  }
}

... neither "foo" nor "bar" is logged.


Solution

  • There's a much simpler way to do this: use a finally block.

    function *source() {
      let i;
    
      try {
        for(i = 0; i < 5; i++)
          yield i;
      }
      finally {
        if(i !== 5)
          console.log('  terminated early');
      }
    }
    
    console.log('First:')
    
    for(const val of source()) {
      console.log(`  ${val}`);
    }
    
    console.log('Second:')
    
    for(const val of source()) {
      console.log(`  ${val}`);
    
      if(val > 2)
        break;
    }
    

    ...yields:

    First:
      0
      1
      2
      3
      4
    Second:
      0
      1
      2
      3
      terminated early