[英]async / await + yield / next order of execution
提前为长篇道歉! 下面是我正在查看的代码示例和日志输出:
const a = () => new Promise( resolve => {
setTimeout( () => resolve('result of a()'), 1000);
});
const b = () => new Promise( resolve => {
setTimeout( () => resolve('result of b()'), 500);
});
const c = () => new Promise( resolve => {
setTimeout( () => resolve('result of c()'), 1100);
});
// async generator function
const MyAsyncGenerator = async function*() {
yield await a();
yield await b();
yield await c();
};
// generator object
const gen = MyAsyncGenerator();
// get 'gen' values
(async () => {
console.log(await gen.next())
console.log(await gen.next())
console.log(await gen.next())
console.log(await gen.next())
})();
(async () => {
await Promise.all([a(), b(), c()]).then(res => console.log(res))
})()
{ value: 'result of a()', done: false }
[ 'result of a()', 'result of b()', 'result of c()' ]
{ value: 'result of b()', done: false }
{ value: 'result of c()', done: false }
{ value: undefined, done: true }
我想弄清楚为什么Promise.all([...]).then()
是第二个记录的。 这是我最好的解释,但非常感谢任何其他见解:
由于有两个匿名异步IIFEs(立即调用函数表达式),而第一gen.next()
评估的结果a()
中, .then()
在新的无极方法返回通过Promise.all()
被推到微任务队列
第一次await gen.next()
记录到控制台后,调用堆栈为空,因此事件循环将.then()
推送到下一个调用堆栈
我最终不确定它是否与任务与微任务队列有关,或者与生成器迭代相关的Promise.all()
何时完成。 我的理解是setTimeout()
进入任务队列,但是如果我们在生成器迭代下的同一个代码块中包含Promise.all()
,则日志是有序的:
(async () => {
console.log(await gen.next())
console.log(await gen.next())
console.log(await gen.next())
console.log(await gen.next())
Promise.all([a(), b(), c()]).then(res => console.log(res))
})();
{ value: 'result of a()', done: false }
{ value: 'result of b()', done: false }
{ value: 'result of c()', done: false }
{ value: undefined, done: true }
[ 'result of a()', 'result of b()', 'result of c()' ]
这是您的程序,其中包含何时发生的时间戳。
@ x ms
表示绝对时间(当然是理想化的), T+x ms
表示相对时间。 当程序启动时, @ 0 ms
事情“同时”发生。
const wait = (value, ms) => new Promise(resolve => setTimeout(() => resolve(value), ms));
const a = () => wait('result of a', 1000);
const b = () => wait('result of b', 600);
const c = () => wait('result of c', 1100);
const MyAsyncGenerator = async function*() {
yield await a(); // T+1000 ms
yield await b(); // T+ 600 ms
yield await c(); // T+1100 ms
};
const gen = MyAsyncGenerator(); // @ 0 ms
(async () => {
console.log(await gen.next()); // @ 1000 ms
console.log(await gen.next()); // @ 1600 ms
console.log(await gen.next()); // @ 2700 ms
console.log(await gen.next()); // @ 2700 ms
})(); // @ 0 ms
(async () => {
await Promise.all([a(), b(), c()]) // @ 0 ms
.then(res => console.log(res)); // @ 1100 ms
})(); // @ 0 ms
由此很明显Promise.all()
将在生成器的第一个和第二个输出之间完成。
请注意,您的第二个函数是无用使用async
/ await
的示例。 await
没有任何内容,因此等待没有意义。 最好写成
(() => {
Promise.all([a(), b(), c()])
.then(res => console.log(res));
})();
而且由于 IIFE 在这里也没有多大意义,所以它会更好
Promise.all([a(), b(), c()])
.then(res => console.log(res));
奖金
const gen2 = MyAsyncGenerator();
(async () => {
console.log(await gen2.next());
console.log(await gen2.next());
console.log(await gen2.next());
console.log(await gen2.next());
})().then(() => {
Promise.all([a(), b(), c()])
.then(res => console.log(res));
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.