【问题标题】:Capturing the Return Value of a JavaScript Iterator捕获 JavaScript 迭代器的返回值
【发布时间】:2020-07-25 23:10:51
【问题描述】:

考虑以下迭代器。它产生字符串 'foo' 和 'bar' 然后返回 'quux' 作为返回值。我可以使用Array.from 从迭代器中提取收益,但如果这样做,我将无法读出返回值。迭代器不再返回返回值,因为 Array.from 已作为协议的一部分接收(并丢弃?)它。

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

我能想到的唯一解决方案是编写一个间谍程序来监视迭代并将返回值存储到预定义的变量中,作为Array.from 丢弃返回值之前的副作用。是否有更好的替代方法来访问返回值?

let quux
const spy = function* (i) { /* extract return value from i and store it to quux */ }
const [foo, bar] = Array.from(spy(iterator))

【问题讨论】:

    标签: javascript iterator


    【解决方案1】:

    你是对的 - 当迭代器 next 函数返回 { done: true, value: 'whatever' } 时,该值被静默丢弃。

    正如您已经说过的,您可以编写一个包装函数(或一个类,如果您愿意的话)。但与其将其保存到外部变量中,不如将其转换为常规迭代值。

    例如:

    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)
    

    (注意:如果没有明确的返回值,那么你会得到undefined 作为最后一个值。)

    但是,那么问题是,为什么你甚至需要达到这些长度?而不是写return 'quux' 你可以写yield 'quux'; return 并实现同样的事情而无需经历所有的箍......

    【讨论】:

    • 在 TypeScript 中会有所不同,因为 Generator<number, number, never> 保证始终包含至少一个数字,而 Generator<number, void, never> 可能不包含任何值。
    • 这是我的代码,以防您感兴趣。这有点乱,但它完成了工作。 CherryDT 的解决方案与我已经在做的非常接近。 github.com/maasglobal/scrapql/blob/master/src/utils/…
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-02
    • 2021-02-17
    • 1970-01-01
    • 2010-12-19
    • 1970-01-01
    • 1970-01-01
    • 2020-09-13
    相关资源
    最近更新 更多