{"_path":"/blogs/javascript/async-await/async-for-each","_draft":false,"_partial":false,"_empty":false,"title":"Async .forEach()","description":"First of all, we need to understand what makes JS code asynchronous. You can check my JS Promises post for a more in depth explanation, but the TLDR is: When a WebAPI call returns a Promise, the current function/loop will always run to completion before the promise's resolve is executed.","excerpt":{"type":"root","children":[{"type":"element","tag":"h1","props":{"id":"how-to-make-a-truly-async-foreach"},"children":[{"type":"text","value":"How to make a truly Async .forEach()"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First of all, we need to understand what makes JS code asynchronous. You can check my "},{"type":"element","tag":"a","props":{"href":"/blogs/javascript/async-await/promises"},"children":[{"type":"text","value":"JS Promises"}]},{"type":"text","value":" post for a more in depth explanation, but the TLDR is: When a WebAPI call returns a "},{"type":"element","tag":"code-inline","props":{},"children":[{"type":"text","value":"Promise"}]},{"type":"text","value":", the current function/loop will always run to completion before the promise's "},{"type":"element","tag":"code-inline","props":{},"children":[{"type":"text","value":"resolve"}]},{"type":"text","value":" is executed."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Now, lets take a look at "},{"type":"element","tag":"code-inline","props":{},"children":[{"type":"text","value":"forEach"}]},{"type":"text","value":". All it does is call the specified function with each value."}]},{"type":"element","tag":"code","props":{"code":"function forEach(callback) {\n for (const element of array) {\n callback(element);\n }\n}\n","language":"JS"},"children":[{"type":"element","tag":"pre","props":{},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"function forEach(callback) {\n for (const element of array) {\n callback(element);\n }\n}\n"}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"As we can see, the next "},{"type":"element","tag":"code-inline","props":{},"children":[{"type":"text","value":"callback"}]},{"type":"text","value":" is executed as soon as the previous one has returned. Since a returned "},{"type":"element","tag":"code-inline","props":{},"children":[{"type":"text","value":"Promise"}]},{"type":"text","value":" will not be awaited, it will execute the next one immediately."}]},{"type":"element","tag":"h2","props":{"id":"applications"},"children":[{"type":"text","value":"Applications"}]},{"type":"element","tag":"h3","props":{"id":"parallel"},"children":[{"type":"text","value":"Parallel"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"So, lets say we want to perform 5 asynchronous api calls. How can we do this?"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If we use "},{"type":"element","tag":"code-inline","props":{},"children":[{"type":"text","value":"forEach"}]},{"type":"text","value":", we will run into some issues:"}]},{"type":"element","tag":"code","props":{"code":"urls.forEach(url => axios.delete(url));\n\nconsole.log('Done?'); // This will run before the API calls have been responded\n\n\nurls.forEach(async (url) => axios.delete(url));\n\nconsole.log('Done?'); // Even passing an async function won't do it\n","language":"JS"},"children":[{"type":"element","tag":"pre","props":{},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"urls.forEach(url => axios.delete(url));\n\nconsole.log('Done?'); // This will run before the API calls have been responded\n\n\nurls.forEach(async (url) => axios.delete(url));\n\nconsole.log('Done?'); // Even passing an async function won't do it\n"}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"This is because each callback will return a "},{"type":"element","tag":"code-inline","props":{},"children":[{"type":"text","value":"Promise"}]},{"type":"text","value":" as soon as the API call is fired. What we want is to pause our function until "},{"type":"element","tag":"strong","props":{},"children":[{"type":"text","value":"all"}]},{"type":"text","value":" requests have finished."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The proper way of doing this is:"}]},{"type":"element","tag":"code","props":{"code":"const promises = urls.map(url => axios.delete(url))\n\ntry {\n const results = await Promise.all(promises)\n\n console.log('All requests executed successfully!!')\n} catch(error) {\n console.error('Some request failed:', error)\n}\n","language":"JS"},"children":[{"type":"element","tag":"pre","props":{},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"const promises = urls.map(url => axios.delete(url))\n\ntry {\n const results = await Promise.all(promises)\n\n console.log('All requests executed successfully!!')\n} catch(error) {\n console.error('Some request failed:', error)\n}\n"}]}]}]},{"type":"element","tag":"h3","props":{"id":"sequential"},"children":[{"type":"text","value":"Sequential"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Now, if you need your calls to happen sequentially, instead of in parallel, the best option is a for loop."}]},{"type":"element","tag":"code","props":{"code":"for(const url of urls) {\n await axios.delete(url)\n}\n\nconsole.log('All calls done!')\n","language":"JS"},"children":[{"type":"element","tag":"pre","props":{},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"for(const url of urls) {\n await axios.delete(url)\n}\n\nconsole.log('All calls done!')\n"}]}]}]}]},"body":{"type":"root","children":[{"type":"element","tag":"h1","props":{"id":"how-to-make-a-truly-async-foreach"},"children":[{"type":"text","value":"How to make a truly Async .forEach()"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"First of all, we need to understand what makes JS code asynchronous. You can check my "},{"type":"element","tag":"a","props":{"href":"/blogs/javascript/async-await/promises"},"children":[{"type":"text","value":"JS Promises"}]},{"type":"text","value":" post for a more in depth explanation, but the TLDR is: When a WebAPI call returns a "},{"type":"element","tag":"code-inline","props":{},"children":[{"type":"text","value":"Promise"}]},{"type":"text","value":", the current function/loop will always run to completion before the promise's "},{"type":"element","tag":"code-inline","props":{},"children":[{"type":"text","value":"resolve"}]},{"type":"text","value":" is executed."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Now, lets take a look at "},{"type":"element","tag":"code-inline","props":{},"children":[{"type":"text","value":"forEach"}]},{"type":"text","value":". All it does is call the specified function with each value."}]},{"type":"element","tag":"code","props":{"code":"function forEach(callback) {\n for (const element of array) {\n callback(element);\n }\n}\n","language":"JS"},"children":[{"type":"element","tag":"pre","props":{},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"function forEach(callback) {\n for (const element of array) {\n callback(element);\n }\n}\n"}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"As we can see, the next "},{"type":"element","tag":"code-inline","props":{},"children":[{"type":"text","value":"callback"}]},{"type":"text","value":" is executed as soon as the previous one has returned. Since a returned "},{"type":"element","tag":"code-inline","props":{},"children":[{"type":"text","value":"Promise"}]},{"type":"text","value":" will not be awaited, it will execute the next one immediately."}]},{"type":"element","tag":"h2","props":{"id":"applications"},"children":[{"type":"text","value":"Applications"}]},{"type":"element","tag":"h3","props":{"id":"parallel"},"children":[{"type":"text","value":"Parallel"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"So, lets say we want to perform 5 asynchronous api calls. How can we do this?"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"If we use "},{"type":"element","tag":"code-inline","props":{},"children":[{"type":"text","value":"forEach"}]},{"type":"text","value":", we will run into some issues:"}]},{"type":"element","tag":"code","props":{"code":"urls.forEach(url => axios.delete(url));\n\nconsole.log('Done?'); // This will run before the API calls have been responded\n\n\nurls.forEach(async (url) => axios.delete(url));\n\nconsole.log('Done?'); // Even passing an async function won't do it\n","language":"JS"},"children":[{"type":"element","tag":"pre","props":{},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"urls.forEach(url => axios.delete(url));\n\nconsole.log('Done?'); // This will run before the API calls have been responded\n\n\nurls.forEach(async (url) => axios.delete(url));\n\nconsole.log('Done?'); // Even passing an async function won't do it\n"}]}]}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"This is because each callback will return a "},{"type":"element","tag":"code-inline","props":{},"children":[{"type":"text","value":"Promise"}]},{"type":"text","value":" as soon as the API call is fired. What we want is to pause our function until "},{"type":"element","tag":"strong","props":{},"children":[{"type":"text","value":"all"}]},{"type":"text","value":" requests have finished."}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"The proper way of doing this is:"}]},{"type":"element","tag":"code","props":{"code":"const promises = urls.map(url => axios.delete(url))\n\ntry {\n const results = await Promise.all(promises)\n\n console.log('All requests executed successfully!!')\n} catch(error) {\n console.error('Some request failed:', error)\n}\n","language":"JS"},"children":[{"type":"element","tag":"pre","props":{},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"const promises = urls.map(url => axios.delete(url))\n\ntry {\n const results = await Promise.all(promises)\n\n console.log('All requests executed successfully!!')\n} catch(error) {\n console.error('Some request failed:', error)\n}\n"}]}]}]},{"type":"element","tag":"h3","props":{"id":"sequential"},"children":[{"type":"text","value":"Sequential"}]},{"type":"element","tag":"p","props":{},"children":[{"type":"text","value":"Now, if you need your calls to happen sequentially, instead of in parallel, the best option is a for loop."}]},{"type":"element","tag":"code","props":{"code":"for(const url of urls) {\n await axios.delete(url)\n}\n\nconsole.log('All calls done!')\n","language":"JS"},"children":[{"type":"element","tag":"pre","props":{},"children":[{"type":"element","tag":"code","props":{"__ignoreMap":""},"children":[{"type":"text","value":"for(const url of urls) {\n await axios.delete(url)\n}\n\nconsole.log('All calls done!')\n"}]}]}]}],"toc":{"title":"","searchDepth":2,"depth":2,"links":[{"id":"applications","depth":2,"text":"Applications","children":[{"id":"parallel","depth":3,"text":"Parallel"},{"id":"sequential","depth":3,"text":"Sequential"}]}]}},"_type":"markdown","_id":"content:blogs:javascript:async-await:async-for-each.md","_source":"content","_file":"blogs/javascript/async-await/async-for-each.md","_extension":"md"}