为什么await表达式作为concat()参数时async/await输出结果不同
问题解答
核心差异
两个函数的本质区别是await语句的位置不同,触发了对数组变量取值时机的差异,进而引发了运行结果的不同。
run1输出[3000]的原因
run1的回调代码为:
output1 = output1.concat([await sleep(sec)])
JS 执行这行代码时,会先计算等号右侧的表达式:
- map生成的3个异步回调几乎同时启动,第一步先读取当前
output1的值,此时所有回调拿到的都是初始空数组的快照[]。 - 遇到
await sleep(sec)后,所有回调暂停执行,等待各自的定时器触发。 - 定时器按1000ms、2000ms、3000ms的顺序先后触发:
- 1000ms回调恢复:用之前存的空数组快照和1000合并,得到
[1000]赋值给output1 - 2000ms回调恢复:用自己之前存的空数组快照和2000合并,得到
[2000],直接覆盖了之前的[1000] - 3000ms回调恢复:同样用空数组快照和3000合并,得到
[3000],覆盖之前的[2000]
- 1000ms回调恢复:用之前存的空数组快照和1000合并,得到
最终output1就只剩最后赋值的[3000]。
run2输出[1000,2000,3000]的原因
run2的回调代码为:
const res = await sleep(sec); output2 = output2.concat([res]);
执行顺序发生了变化:
- 3个异步回调启动后直接遇到
await sleep(sec)进入暂停,此时还没有读取output2的值。 - 定时器按顺序触发:
- 1000ms回调恢复:拿到
res=1000,此时读取当前最新的output2(初始[]),合并得到[1000]赋值给output2 - 2000ms回调恢复:拿到
res=2000,读取当前最新的output2(已经是[1000]),合并得到[1000,2000]赋值 - 3000ms回调恢复:拿到
res=3000,读取当前最新的output2(已经是[1000,2000]),合并得到最终的[1000,2000,3000]
- 1000ms回调恢复:拿到
你之前对output2的认知是正确的,所有异步回调共享同一个output2变量,赋值时读取的是最新的数组值,因此结果可以正常累加。
内容的提问来源于stack exchange,提问作者ikhvjs
相关产品推荐
相关产品推荐

