异步Await映射未等待异步函数在映射下一项之前在映射函数内部完成



我有一个正在映射的数组,在映射函数内部,我正在调用一个异步函数,该函数使用request-promise执行返回promise的异步请求。

我希望数组的第一个项被映射,执行请求,然后第二个项重复相同的过程。但这种情况并非如此。

这是我的职责;

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

CCD_ 2如下;

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()不是异步的,也不是承诺感知的。它只是尽职尽责地获取您从其回调中返回的值,并将其填充到结果数组中。即使在你的情况下这是一个承诺,它仍然会继续,而不是等待那个承诺。在这方面,您无法更改.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;
}

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

您可以尝试替换此行:

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

带有:

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

与for循环备选方案相比,nodejs的工作方式应该更多,在这种情况下,只有forEach被禁止。

最新更新