Here is my code in typescript:
import _ from "lodash";
const waitWithPromise = (index, ms): Promise<void> =>
new Promise((resolve) => {
console.log(`${index}: starting ${Date.now()}`);
setTimeout(() => {
console.log(`${index}: ending ${Date.now()}`);
resolve();
}, ms);
});
const waitWithAsync = (index: number, ms: number) => async (): Promise<void> => {
await waitWithPromise(index, ms);
};
// eslint-disable-next-line @typescript-eslint/require-await
void (async (): Promise<void> => {
const functionToPromiseArray = _.range(0, 9).map((index) => {
return waitWithAsync(index, Math.random() * 1000);
});
let i = 0;
const groupSize = 3;
for (const functionToPromiseGroup of _.chunk(
functionToPromiseArray,
groupSize
)) {
console.log(`***********************
GROUP ${i + 1} / ${Math.ceil(functionToPromiseArray.length / groupSize)}
SIZE ${functionToPromiseGroup.length}
***********************`);
await Promise.all(
functionToPromiseGroup.map((functionToPromise) =>
functionToPromise()
)
);
i++;
}
console.log(`finished! ${Date.now()}`);
})();
Output:
***********************
GROUP 1 / 3
SIZE 3
***********************
0: starting 1635274115798
1: starting 1635274115799
2: starting 1635274115799
0: ending 1635274116358
1: ending 1635274116375
2: ending 1635274116512
***********************
GROUP 2 / 3
SIZE 3
***********************
3: starting 1635274116512
4: starting 1635274116512
5: starting 1635274116512
4: ending 1635274116899
5: ending 1635274117094
3: ending 1635274117432
***********************
GROUP 3 / 3
SIZE 3
***********************
6: starting 1635274117432
7: starting 1635274117432
8: starting 1635274117432
8: ending 1635274117863
6: ending 1635274118051
7: ending 1635274118412
finished! 1635274118412
This appears to run the way I want: wait for one group to finish before moving on to the next. Here's the thing that makes me doubt that: if I replace the body of waitWithPromise
to be this:
const waitWithPromise = (item, index): Promise<void> =>
new Promise((resolve) => {
console.log(`${index}: starting time=${Date.now()}`);
void axios({
method: "POST",
url: "...",
data: item.body,
headers: { signature: item.signature },
})
.then((response) => {
console.log(
`${index}: success ${JSON.stringify(response.status)}`
);
})
.catch((error) => {
console.log(
`${index}: fail ${JSON.stringify(
error
)} item=${JSON.stringify(item)} time=${Date.now()}`
);
})
.finally(() => {
resolve();
});
});
The output remains in the correct order, but a lot of the time, it pauses for a few seconds while one group completes, then I see a bunch of groups fly by in a flurry. It's almost like the next few groups already received their results, they were just waiting to print them.
Since this is making a call over the network, it doesn't make sense to me that it could complete 3+ groups -- in my real production code, there's 10 axios requests in each group -- faster than the human eye can see. They all succeed, btw; it's not like they're going fast because the server is rejecting them.
So, is this example working the way I think, or does it have some flaw?