To clarify. The fetch call within ther async functions is being called even if i delete the last line of code. Namely:Â
let results = await Promise.all(promises.flat());
Hey ​@Mitchel Wijt,
Yes, having a problem like this can definitely feel frustrating!
Here’s what you want instead and I’ll explain why:
Â
let promises = records.flatMap((record) => {
return r
() => asyncFunctionWithFetchCall1(record),
() => asyncFunctionWithFetchCall2(record),
];
});
// Now start all at once when you're ready
let results = await Promise.all(promises.map(fn => fn()));
What we’re doing here is storing a list of functions that will return the promise when executed in `promises`. Then we’re starting them all at once with `Promise.all`.
How is this different from the below?
let firstPromise = asyncFunctionWithFetchCall1(record);
In this line you are still actually executing the function immediately, event though it’s async. The await
keyword waits for a promise to resolve — it doesn't defer when the promise is created or when the async function starts running.
I hope this helps! If you need more examples just let me know--this isn’t easy concept to wrap your head around!
When you do
let firstPromise = asyncFunctionWithFetchCall1(record);
You’re not just declaring a promise, you're calling the function, which means the code inside asyncFunctionWithFetchCall1
(including any fetch
calls) runs immediately, regardless of whether you await it or not.
You want to defer execution of the fetch calls, only starting them inside Promise.all
. To do that, wrap your function calls in anonymous functions and only execute them when needed as showed by ​@BuildForATÂ
Taha, Airtable Advisor
Hey ​@BuildForATÂ
Thank you for the quick response and explanation!Â
This is pretty interesting, I never encountered this before in my IDE with JS/TS. I am used to always calling the function without await creating an array of Promise objects and resolving all of them with Promise.all.
Is this happening because I am doing something different in the .map() function? just curious :)
What is not really clear to me is. My fetch call inside the async function has an await keyword, but since the parent function is called without an await keyword, shouldn't this entire fetch function just not execute?Â
Doing the same .map() function in my own Node API produces the results I expect which is not executing the promises inside the async function until I await the parent Promise.all function.
I will try this out, thank you!Â
Â
Great questions ​@Mitchel Wijt!
If you could share that code with me I could tell you exactly what the difference is.
Â
But, to give you more context, once a promise is created it will immediately start executing. All that `await` does is it waits for the result of the promise before it moves to the next line of code. So, if there’s no `await` there, then the program will just start executing the next line (even if the async function isn’t done running). This should be regardless of the environment that JS is running.
Â
Now, I’m really curious to see what your other code looks like!
Â
​@BuildForATÂ
These are 2 examples in my codebase that work as expected :)Â
 const tracks = await Promise.all(trackIds.map((id) => {
      return Track.selectById(id);
    }));
Â
let promises = >];
    records.forEach((record) => {
      promises.push(createBumaForm(record))
      promises.push(createLabelCopy(record));
    })
    await Promise.all(promises);
If `Track.selectById(id)`, `createBumaForm(record)`, and `createLabelCopy(record)` all return promises then I do expect them to start executing even if you remove the `await Promise.all()`
Â
Would it be possible to share some of the structure of say `createBumaForm(record)` itself? Please remove any sensitive information.