有什么办法可以从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'
非常感谢:)
答案 0 :(得分:4)
您的asyncIterator
有一个错误:承诺must be a result object的实现值(实现IteratorResult interface的对象,其形状为{done, value}
)。但是,您将使用字符串来实现诺言。
如果将其更新为返回结果对象,则会看到返回:
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
还有另一个问题(不一定是错误):它不继承自%AsyncIteratorPrototype%及其下面的链。从理论上讲,代码可以将方法添加到%AsyncIteratorPrototype%,%IteratorPrototype%等中,而asyncIterator
中将缺少这些方法。
通常,异步生成器函数是创建异步迭代器对象的最佳方法(因为异步生成器是异步迭代器),就像非异步生成器函数是创建迭代器的最佳方法一样。您将获得yield
语法并从标准原型继承的好处。
也就是说,如果您使用异步生成器函数实现了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;
}