首页 > 解决方案 > Promise.all() 中的第一个承诺没有正确执行

问题描述

wait函数用作睡眠函数,fn函数接受一个数组(项目),它记录每个项目并在记录下一个项目之前休眠一秒钟。

const wait = async(time) => {
  return new Promise((resolve) => setTimeout(resolve, time))
}

const fn = async(items) => {
  for (item of items) {
    await wait(1000)
    console.log(item)
  }
}

const exeAll = async() => {
  Promise.all([
    fn(['A1', 'A2']),
    fn(['B1', 'B2']),
  ])
}

exeAll()

问题是exeAll打印的函数提供的结果:

B1
A2
B2
B2

但我认为它应该打印如下内容:

A1
B1
A2
B2

执行上述代码时,A1 根本不显示。谁能解释为什么?

标签: javascriptasynchronousasync-awaitpromise

解决方案


for (item of items) {会创建一个隐式全局变量item,即多次调用fn会互相干扰,覆盖item。正确声明变量并按预期工作:

const wait = async(time) => {
  return new Promise((resolve) => setTimeout(resolve, time))
}

const fn = async(items) => {
  for (let item of items) {
  //   ^^^^
    await wait(1000)
    console.log(item)
  }
}

const exeAll = async() => {
  Promise.all([
    fn(['A1', 'A2']),
    fn(['B1', 'B2']),
  ])
}

exeAll()


我们可以添加更多日志记录以fn查看在您的情况下会发生什么:

const wait = async(time) => {
  return new Promise((resolve) => setTimeout(resolve, time))
}

let counter = 0;
const fn = async(items) => {
  const c = counter++;
  console.log(`enter fn call #${c}`);
  for (item of items) {
    console.log(`fn call #${c} sets item <-`, item);
    await wait(1000)
     console.log(`fn call #${c} reads item ->`, item);
    console.log(item)
  }
}

const exeAll = async() => {
  Promise.all([
    fn(['A1', 'A2']),
    fn(['B1', 'B2']),
  ])
}

exeAll()


严格模式 ( "use strict";) 会发现该错误,因为分配给未声明的变量会引发错误。


推荐阅读