使用javascript的Symbol.asyncIterator来等待循环
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用javascript的Symbol.asyncIterator来等待循环相关的知识,希望对你有一定的参考价值。
我想了解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
并在同一个对象上插入一个键Symbol.asyncIterator
并为其分配一个名为test
的函数,它返回一个Promise
。然后我使用for await of
循环迭代函数将返回的所有值。
我做错了什么?
PS:我在节点版本10.13.0
和最新版本的Chrome
上
要成为有效的asyncIterator
,你的test
函数必须返回一个带有next
方法的对象,该方法返回带有value
和done
属性的结果对象的promise。 (从技术上讲,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))
test
函数不能返回一个promise,而是一个Iterator(一个带有next()
的对象)方法,该方法必须返回一个Promise(使它成为一个异步迭代器)并且Promise必须解析为包含value
的对象和一个done
键:
function test()
return
next()
return Promise.resolve( value: "test", done: false );
;
现在虽然有效,但它还没那么有用。但是,您可以使用异步生成器函数创建相同的行为:
async function* test()
await Promise.resolve();
yield "test";
或者在你的情况下:
async function* test()
for(let i = 0; i < 10; i++)
if(i > 5)
await Promise.resolve();
yield `Greater than 5: ($i)`;
else
await Promise.resolve();
yield `Less than 5: ($i)`;
你应该使test
成为async
生成器函数,而yield
而不是return
:
let a =
async function* test()
for(let i=0; i < 10; i++)
if(i > 5)
yield Promise.resolve(`Greater than 5: ($i)`)
else
yield Promise.resolve(`Less than 5: ($i)`)
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.asyncIterator来等待循环的主要内容,如果未能解决你的问题,请参考以下文章