我试图理解 javascript 的 Symbol.asyncIterator和 for await of .我写了一些简单的代码,它抛出一个错误说:
TypeError: undefined is not a function
在尝试使用
for await (let x of a)
的行上.我无法理解它的原因。
let a = {}
function test() {
for(let i=0; i < 10; i++) {
if(i > 5) {
return Promise.resolve(`Greater than 5: (${i})`)
}else {
return Promise.resolve(`Less than 5: (${i})`)
}
}
}
a[Symbol.asyncIterator] = test;
async function main() {
for await (let x of a) { // LINE THAT THROWS AN ERROR
console.log(x)
}
}
main()
.then(r => console.log(r))
.catch(err => console.log(err))
我创建了一个空对象
a
并插入一个 key Symbol.asyncIterator
在同一个对象上并为其分配一个名为 test
的函数返回 Promise
.然后我使用 for await of
循环遍历函数将返回的所有值。我做错了什么?
PS:我是Node版本
10.13.0
以及最新版本的 Chrome
最佳答案
要成为有效的 asyncIterator
,您的 test
函数必须返回具有 next
方法的对象,该方法返回具有 value
和 done
属性的结果对象的 promise 。 (从技术上讲,如果 value
的值为 undefined
,则 done
是可选的,如果其值为 false
,则 async
是可选的,但是......)
您可以通过以下几种方式做到这一点:
您可以完全手动完成(这不会尝试获得正确的原型(prototype)):
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))
您可以半手动编写一个函数,该函数使用
next
async
方法返回一个对象(仍然没有尝试获得正确的原型(prototype)):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))
或者您可以只使用
Symbol.iterator
生成器函数(最简单,并自动获取正确的原型(prototype)):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))
关于原型(prototype):您从 JavaScript 运行时本身获得的所有异步迭代器都继承自原型(prototype),该原型(prototype)提供了确保迭代器也是可迭代的非常基本的特性(通过让
this
成为返回 next
的函数)。该原型(prototype)没有公开可用的标识符或属性,您必须跳过箍才能获得它:const asyncIteratorPrototype =
Object.getPrototypeOf(
Object.getPrototypeOf(
async function*(){}.prototype
)
);
然后,您将使用它作为对象的原型(prototype),并使用您返回的 ojit_code 方法:
return Object.assign(Object.create(asyncIteratorPrototype), {
next() {
// ...
}
});
关于javascript - 使用 javascript 的 Symbol.asyncIterator 和 for await 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55531247/