Suh*_*pta 5 javascript node.js async-iterator ecmascript-2018
我正在尝试了解 javascript 的Symbol.asyncIterator和await of。我写了一些简单的代码,它抛出一个错误说:
TypeError: undefined is not a function
Run Code Online (Sandbox Code Playgroud)
在尝试使用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))
Run Code Online (Sandbox Code Playgroud)
我创建一个空对象a并Symbol.asyncIterator在同一个对象上插入一个键,并为其分配一个名为的函数test,该函数返回一个Promise. 然后我使用for await of循环来迭代函数将返回的所有值。
我做错了什么?
PS:我使用的是 Node 版本10.13.0和最新版本的Chrome
要成为有效的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))Run Code Online (Sandbox Code Playgroud)
您可以半手动编写一个函数,该函数返回一个带有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))Run Code Online (Sandbox Code Playgroud)
或者你可以只使用一个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))Run Code Online (Sandbox Code Playgroud)
关于原型:您从 JavaScript 运行时本身获得的所有异步迭代器都继承自一个原型,该原型提供了确保迭代器也是可迭代的非常基本的特性(通过Symbol.iterator成为一个返回 的函数this)。该原型没有公开可用的标识符或属性,您必须跳过箍才能获得它:
const asyncIteratorPrototype =
Object.getPrototypeOf(
Object.getPrototypeOf(
async function*(){}.prototype
)
);
Run Code Online (Sandbox Code Playgroud)
然后,您将使用它作为next您返回的方法的对象的原型:
return Object.assign(Object.create(asyncIteratorPrototype), {
next() {
// ...
}
});
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2836 次 |
| 最近记录: |