Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Capturing the Return Value of a JavaScript Iterator

Consider the following iterator. It yields strings 'foo' and 'bar' and then returns 'quux' as a return value. I can use Array.from to extract the yields from the iterator but if I do this, I have no way of reading out the return value. The return value is no longer returned by the iterator since Array.from already received (and discarded?) it as part of the protocol.

const iterator = (function* () {
  yield 'foo'
  yield 'bar'
  return 'quux'
})()
const [foo, bar] = Array.from(iterator)
const quux = // ???

The only solution I can think of is writing a spy procedure that monitors the iteration and stores the return value into a predefined variable as a side effect before Array.from discards the return value. Are there better alternative ways of accessing the return value?

let quux
const spy = function* (i) { /* extract return value from i and store it to quux */ }
const [foo, bar] = Array.from(spy(iterator))
like image 943
cyberixae Avatar asked Oct 26 '25 06:10

cyberixae


1 Answers

You are right - when the iterator next function returns { done: true, value: 'whatever' } the value is silently discarded.

As you already said, you could write a wrapper function (or a class, if you wanted to). But instead of saving it to an external variable, you could make it convert this last value to a regular iterated value.

For example:

function* yieldFinal (iterator) {
  let done, value
  do {
    ({ done, value } = iterator.next())
    yield value
  } while (!done)
}

const iterator = (function* () {
  yield 'foo'
  yield 'bar'
  return 'quux'
})()

const [foo, bar, quux] = Array.from(yieldFinal(iterator))

console.log(foo, bar, quux)

(Note: If there was no explicit return value, then you'd get undefined for the last value.)

But, then the question is, why do you even need to go to these lengths? Instead of writing return 'quux' you could write yield 'quux'; return and achieve the same thing without going through all the hoops...

like image 102
CherryDT Avatar answered Oct 28 '25 18:10

CherryDT



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!