异步等待地图在映射下一个项目之前不等待异步函数在地图函数内部完成

Async Await map not awaiting async function to complete inside map function before mapping next item

我有一个正在映射的数组,在我调用异步函数的映射函数中,它正在执行异步请求并使用 request-promise.

返回承诺

我希望映射数组的第一项,执行请求,然后第二项重复相同的过程。但这不是本例中发生的情况。

这是我的功能;

const fn = async() => {
  const array = [0, 1, 2];
  console.log('begin');
  await Promise.all(array.map(item => anAsyncFunction(item)));
  console.log('finished');
  return;
}

anAsyncFunction如下;

const anAsyncFunction = async item => {
  console.log(`looping ${item}`);
  const awaitingRequest = await functionWithPromise(item);
  console.log(`finished looping ${item}`);
  return awaitingRequest;
}

functionWithPromise提出请求的地方

const functionWithPromise = async (item) => {
  console.log(`performing request for ${item}`);
  return Promise.resolve(await request(`https://www.google.com/`).then(() => {
    console.log(`finished performing request for ${item}`);
    return item;
  }));
}

从我得到的控制台日志;

begin
looping 0
performing request for 0
looping 1
performing request for 1
looping 2
performing request for 2
finished performing request for 0
finished looping 0
finished performing request for 1
finished looping 1
finished performing request for 2
finished looping 2
finished

然而,我想要的是

begin
looping 0
performing request for 0
finished performing request for 0
finished looping 0
looping 1
performing request for 1
finished performing request for 1
finished looping 1
looping 2
performing request for 2
finished performing request for 2
finished looping 2
finished

我通常可以接受这种模式,但我似乎从请求调用中得到了一些无效的正文,因为我可能一次制作了太多。

对于我想要实现的目标,有没有更好的方法

.map() 不支持异步或承诺。它只是尽职尽责地从回调中获取 return 的值,并将其填充到结果数组中。即使在您的情况下这是一个承诺,它仍然会继续进行,而不是等待那个承诺。而且,在这方面您无法更改 .map() 行为。这就是它的工作方式。

相反,使用 for 循环,然后 await 循环内的异步函数,这将暂停循环。


你的结构:

await Promise.all(array.map(item => anAsyncFunction(item)));

是 运行并行调用所有 anAsyncFunction(),然后等待所有调用完成。


按顺序 运行 它们,使用 for 循环和 await 单独的函数调用:

const fn = async() => {
  const array = [0, 1, 2];
  console.log('begin');
  for (let item of array) {
      await anAsyncFunction(item);
  }
  console.log('finished');
  return;
}

知道 none 的数组迭代方法是异步感知的很重要。这包括 .map().filter().forEach() 等...因此,如果您想在循环内等待某些内容以便对异步操作进行排序,请使用常规 for 循环,它是 async 感知的并将暂停循环。

您可以尝试替换此行:

await Promise.all(array.map(item => anAsyncFunction(item)));

与:

await Promise.all(array.map(async(item) => await anAsyncFunction(item)));

nodejs 的工作方式应该比 for 循环替代方案更多,在这种情况下只有 forEach 是禁止的。