要成为有效的asyncIterator
,您的test
函数必须返回一个对象,该对象的next
方法返回具有value
和done
属性的结果对象的承诺。(从技术上讲,value
如果它的值是可选的,如果它的值undefined
是done
可选的false
,但是......)
您可以通过以下几种方式做到这一点:
- 完全手动(尴尬,特别是如果您想要正确的原型)
- 半手动(稍微不那么尴尬,但获得正确的原型仍然很尴尬)
- 使用异步生成器函数(最简单)
您可以完全手动完成(这不会尝试获得正确的原型):
function test() {
let i = -1;
return {
next() {
++i;
if (i >= 10) {
return Promise.resolve({
value: undefined,
done: true
});
}
return Promise.resolve({
value: i > 5 ? `Greater than 5: (${i})` : `Less than 5: (${i})`,
done: false
});
}
};
}
let a = {
[Symbol.asyncIterator]: test
};
async function main() {
for await (let x of a) {
console.log(x)
}
}
main()
.then(r => console.log(r))
.catch(err => console.log(err))
您可以半手动编写一个返回带有async
next
方法的对象的函数(仍然不尝试获得正确的原型):
function test() {
let i = -1;
return {
async next() {
++i;
if (i >= 10) {
return {
value: undefined,
done: true
};
}
return {
value: i > 5 ? `Greater than 5: (${i})` : `Less than 5: (${i})`,
done: false
};
}
};
}
let a = {
[Symbol.asyncIterator]: test
};
async function main() {
for await (let x of a) {
console.log(x)
}
}
main()
.then(r => console.log(r))
.catch(err => console.log(err))
或者您可以只使用async
生成器函数(最简单,并自动获取正确的原型):
async function* test() {
for (let i = 0; i < 10; ++i) {
yield i > 5 ? `Greater than 5: (${i})` : `Less than 5: (${i})`;
}
}
let a = {
[Symbol.asyncIterator]: test
};
async function main() {
for await (let x of a) {
console.log(x)
}
}
main()
.then(r => console.log(r))
.catch(err => console.log(err))
关于原型:您从 JavaScript 运行时本身获得的所有异步迭代器都继承自原型,该原型提供了确保迭代器也是可迭代的基本特性(通过Symbol.iterator
返回函数this
)。该原型没有公开可用的标识符或属性,您必须跳过箍才能获得它:
const asyncIteratorPrototype =
Object.getPrototypeOf(
Object.getPrototypeOf(
async function*(){}.prototype
)
);
然后,您将使用它作为对象的原型,并使用next
您返回的方法:
return Object.assign(Object.create(asyncIteratorPrototype), {
next() {
// ...
}
});