简体   繁体   English

异步等待 map 不等待异步 function 在 map ZC1C425268E68385D14ZA7 映射之前完成

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

I have an array that I am mapping, inside the map function I am calling an asynchronous function, that is performing an asynchronous request returning a promise using request-promise . I have an array that I am mapping, inside the map function I am calling an asynchronous function, that is performing an asynchronous request returning a promise using request-promise .

I am expecting the first item of the array be mapped, perform the request and then the second item repeats the same process.我期待数组的第一项被映射,执行请求,然后第二项重复相同的过程。 But that's not what is happening in this instance.但这不是在这种情况下发生的事情。

This is my function;这是我的 function;

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

anAsyncFunction is as follows; anAsyncFunction如下;

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

And functionWithPromise where the request is made以及发出请求的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;
  }));
}

From the console logs I get;从我得到的控制台日志中;

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

However, what I want is然而,我想要的是

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

I'd normally be fine with this pattern but I seem to be getting some invalid body from the request call as I may be making too many at once.我通常对这种模式很好,但我似乎从请求调用中得到了一些无效的正文,因为我可能一次制作了太多。

Is there a better method for what I am trying to achieve有没有更好的方法来实现我想要实现的目标

.map() is not async or promise aware. .map()不是异步或承诺感知的。 It just dutifully takes the value you return from its callback and stuffs it in the result array.它只是尽职尽责地获取您从其回调返回的值并将其填充到结果数组中。 Even though it's a promise in your case, it still just keeps on going, not waiting for that promise.即使在你的情况下这是一个承诺,它仍然会继续前进,而不是等待那个承诺。 And, there is nothing you can do in that regard to change the .map() behavior.而且,在这方面您无能为力来更改.map()行为。 That's just the way it works.这就是它的工作方式。

Instead, use a for loop and then await your async function inside the loop and that will suspend the loop.相反,使用for循环,然后在循环内await您的异步函数,这将挂起循环。


Your structure:你的结构:

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

is running all the anAsyncFunction() calls in parallel and then waiting for all of them to finish.正在并行运行所有anAsyncFunction()调用,然后等待所有调用完成。


To run them sequentially, use a for loop and await the individual function call:要按顺序运行它们,请使用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;
}

This is an important thing to know that none of the array iteration methods are async aware.要知道没有一个数组迭代方法是异步感知的,这一点很重要。 That includes .map() , .filter() , .forEach() , etc... So, if you want to await something inside the loop in order to sequence your async operations, then use a regular for loop which is async aware and will pause the loop.这包括.map().filter().forEach()等......所以,如果你想在循环中等待一些东西以对你的异步操作进行排序,那么使用一个async感知的常规for循环并将暂停循环。

You can try replacing this line:您可以尝试替换此行:

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

with:和:

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

Should work more nodejs way than for loop alternative, only forEach is to ban in this case.应该比 for 循环替代更多的 nodejs 方式,在这种情况下只有 forEach 是禁止的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM