有什么办法可以从yield * asyncIterator返回吗?

背景:

给定这样的异步迭代器:

const asyncIterator = {
  next () {
    return new Promise(resolve => setTimeout(() => resolve('next'), 500))
  },
  return () {
    return Promise.resolve('return')
  },
  [Symbol.asyncIterator] () {
    return this
  }
}

以下将永远不会调用其return方法:

async * yieldFromIterator () {
  yield 'start'
  yield * asyncIterator
}

const yieldingIterator = yieldFromIterator()
console.log(await yieldingIterator.next()) // 'start'
console.log(await yieldingIterator.next()) // 'next'
console.log(await yieldingIterator.return()) // never resolved

这也没有:

async * yieldFromIterator () {
  yield 'start'
  for await (const result of asyncIterator) {
    yield result
  }
}

const yieldingIterator = yieldFromIterator()
console.log(await yieldingIterator.next()) // 'start'
console.log(await yieldingIterator.next()) // 'next'
console.log(await yieldingIterator.return()) // never resolved

当然可以做到以下几点:

async * returnIterator () {
  yield 'start'
  return asyncIterator
}

const returningIterator = returnIterator()
console.log(await returningIterator.next()) // 'start'
console.log(await returningIterator.next()) // 'next'
console.log(await returningIterator.return()) // 'return'

非常感谢你 :)

最佳答案

您的asyncIterator发生错误:promise must be a result object(实现IteratorResult interface的对象,其形状为{done, value})的实现值。但是,您将使用字符串来实现 promise 。

如果更新它以返回结果对象,则将看到返回:

const asyncIterator = {
  next () {
    return new Promise(resolve => setTimeout(() => resolve({value: 'next', done: false}), 500))
  },
  return () {
    return Promise.resolve({value: 'return', done: true})
  },
  [Symbol.asyncIterator] () {
    return this
  }
}

async function * yieldFromIterator () {
  yield 'start'
  yield * asyncIterator
}

(async function() {
  const yieldingIterator = yieldFromIterator()
  console.log(await yieldingIterator.next())   // {value: 'start', done: false}
  console.log(await yieldingIterator.next())   // {value: 'next', done: false}
  console.log(await yieldingIterator.return()) // {value: 'return', done: true}
})().catch(error => {
  console.error(error)
})
.as-console-wrapper {
    max-height: 100% !important;
}



另外,asyncIterator还有另一个问题(不一定是bug):它不继承自%AsyncIteratorPrototype%及其下面的链。从理论上讲,代码可以将方法添加到%AsyncIteratorPrototype%,%IteratorPrototype%等中,而asyncIterator中将缺少这些方法。

通常,异步生成器函数是创建异步迭代器对象的最佳方法(因为异步生成器是异步迭代器),就像非异步生成器函数是创建迭代器的最佳方法一样。您可以从yield语法中受益并从标准原型(prototype)中继承。

就是说,如果您使用异步生成器函数实现了asyncIterator,您将看不到响应该'return'调用的return字符串。您需要调用next,并在return中使用yieldFromIterator:

const delay = (ms, ...args) => new Promise(resolve => setTimeout(resolve, ms, ...args));

const asyncIterator = (async function*() {
  await delay(500);
  yield 'next';
  return 'return';
})();

async function * yieldFromIterator () {
  yield 'start'
  return yield * asyncIterator // <=== Added `return`
}

(async function() {
  const yieldingIterator = yieldFromIterator()
  console.log(await yieldingIterator.next()) // {value: 'start', done: false}
  console.log(await yieldingIterator.next()) // {value: 'next', done: false}
  console.log(await yieldingIterator.next()) // {value: 'return', done: true}
  // Changed to `next` −−−−−−−−−−−−−−^
})().catch(error => {
  console.error(error)
})
.as-console-wrapper {
    max-height: 100% !important;
}

关于javascript - 如何从 yield 中获得返回*,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59576490/

10-12 04:28