Promise.all内首个Promise执行异常,A1未打印问题原因求解
问题根因
- 第一个也是最核心的问题是循环变量未声明导致全局污染:你代码里
for (item of items)没有给item加let/const声明,这个变量会被隐式定义为全局变量,两个并行执行的fn异步任务会共享、修改同一个全局item:
第一个fn启动后进入1s等待,此时第二个fn也启动,会把全局item赋值为B1,覆盖了第一个fn原本要打印的A1,等1s到点后两个fn拿到的都是被覆盖后的item值,自然就不会打印A1,后续迭代继续修改同一个全局变量,就会出现重复打印B2这类异常结果。 - 次要问题是你当前的并行执行两个
fn的逻辑本身无法实现你预期的稳定交替输出效果,两个独立的异步任务并行运行时,就算解决了变量问题,也会出现第一秒同时打印A1和B1、第二秒同时打印A2和B2的结果,两者的打印顺序可能随机互换。
修复方案
1. 先解决变量污染导致打印异常的问题
给循环变量加let声明即可,修复后代码如下:
const wait = async(time) => { return new Promise((resolve) => setTimeout(resolve, time)) } const fn = async(items) => { // 给item加let声明,隔离作用域,避免全局污染 for (let item of items) { await wait(1000) console.log(item) } } const exeAll = async() => { // 加await更规范,确保后续逻辑能感知到所有任务执行完成 await Promise.all([ fn(['A1', 'A2']), fn(['B1', 'B2']), ]) } exeAll()
运行该代码的输出为:
A1 B1 A2 B2
注:A1和B1几乎同时打印,顺序可能互换,A2和B2同理。
2. 如果要严格保证输出顺序和你预期完全一致、不会出现顺序互换
需要调整执行逻辑,不要并行调用两个fn,改为按顺序读取对应元素打印:
const wait = async(time) => { return new Promise((resolve) => setTimeout(resolve, time)) } const exeAll = async() => { const arr1 = ['A1', 'A2'] const arr2 = ['B1', 'B2'] for(let i = 0; i < arr1.length; i++) { await wait(1000) console.log(arr1[i]) console.log(arr2[i]) } } exeAll()
该代码运行后会严格按照你预期的顺序输出,每间隔1秒打印一组内容。
内容的提问来源于stack exchange,提问作者H.B.
相关产品推荐
相关产品推荐

