Loop actions can vary, and within the loop, there are different actions that we might work with. Some of these actions might be synchronous and some can be asynchronous.
For scenarios of asynchronous actions within loops (especially for loops), we need to make sure we allows them finish before we can move on to the next iteration.
In this article, we will detail how to wait for loop to finish in Node.js (JavaScript) using two methods.
Introducing Promises
Before we move into Promises, we need to discuss callbacks. Callbacks
are functions passed to other functions and are executed when a specific
code runs, so the functions that will be passed will have to finish
their actions before being used by the other function.
A simple illustration can be seen below where we pass the help
function as an argument of the cli function.
function help(tool) {
console.log("The " + tool + " documentation is here thus");
}
function cli(callback) {
let tool = prompt("Need Help? Enter Tool Name: ");
console.log("Checking the database for the tool passed");
callback(tool);
}
cli(help);
When we pass dgf within the prompt, our output becomes
Checking the database for the tool passed
The dgf documentation is here thus
JavaScript is asynchronous by nature so any long-running task will be
queued, and will move on to other tasks. Therefore, with task such as
networks calls, we can deal with undefined values using callbacks.
However, code with multiple callbacks can easily become messy and hard
to maintain. This phenomenon is called
callback hell. To deal with this, Promises are
helpful and better to use.
The Promise object represents the eventual completion or failure of a
JavaScript asynchronous operation and its resulting value, and it
returns a Promise that will provide the resulting value when its
needed within the code later.
To illustrate Promises, we can create a code that takes a URL and
processes its response. The resolve deals for situation where the code
succeeds, and the reject kicks in where the code fails.
function getData(url) {
return new Promise((resolve, reject) => {
if (!url) {
reject("No URL provided");
}
const xhr = new XMLHttpRequest();
xhr.open("GET", url);
xhr.send();
xhr.onload = function () {
if (xhr.status === 200) {
resolve(xhr.responseText);
} else {
reject(xhr.status);
}
};
});
}
const url = prompt("Enter a URL");
getData(url)
.then((result) => {
console.log("Success!"); // Runs on success
console.log(result);
}).catch(status => {
console.log(`An error with status code ${status} occurred: `); // Runs on error
});
When we pass the
https://reqres.in/api/users?page=2 as
the input to the prompt, the output becomes
Success!
{"page":2,"per_page":6,"total":12,"total_pages":2,"data":
...
The .then() will be triggered when the getData function is
successful, but the .catch() comes in when there is an error.
For our case scenario of dealing with waiting for loop to finish in
Node.js, we will need this basic understanding of Promisies and
asynchronous programming.
Using async/await to wait for loop to finish
With async/await keywords, we can enable Promise-based behaviour and
asynchronous execution within our code. So, for use to wait for the loop
to finish, we can define an async function and wait its result within.
Method 1: for…of loop
If we have iterables that we need to go over with a for loop but will need to carry out some asynchronous operations on (such as a network call), we can define our iteration using the below code
function wrap() {
return new Promise((resolve) => setTimeout(resolve, 500));
}
async function logging(num) {
await wrap();
console.log(num);
}
async function printElement(array) {
for (const num of array) {
await logging(num);
}
console.log("Operation Completed.");
}
printElement([1, 2, 4]);
Output
1
2
4
Operation Completed.
The wrap() function holds the Promise object that will deal with the
resolve situation within the code. Afterwards, we define an
asynchronous function (logging) that logs the numbers we are
iterating over but we await the wrap() function before logging the
numbers.
From here, we define another asynchronous function (printElement)
that will loop over the array and execute the logging function.
Method 2: Use Promise.all
Promise.all method takes an iterable of promises and returns a single
Promise that will be fulfilled only when all the promises within it has
been fulfilled. Since we have an iterable, we can make use of this
method to initialize Promise for each, and then the method will return
a Promise when all the Promises for each iteration has been fulfilled.
To achieve that, we can adjust the printElement function as thus by
mapping the array to promises and waiting for all promises to be
resolved before moving one.
async function printElement(array) {
const promises = array.map(logging);
await Promise.all(promises);
console.log("Operation Completed.")
}
Output
1
2
4
Operation Completed
Summary
To wait for all operations within a loop iteration to finish, Promises
are your best bet to dealing with such situations. Each method are
effective in dealing with such, however, the Promise.all method which
will run all the attached functions in parallel can make for a
cumbersome approach in very large arrays.
References
Promise.all() - JavaScript | MDN
(mozilla.org)
Promise - JavaScript | MDN
(mozilla.org)

![Wait For Loop to Finish in Node.js [SOLVED]](/wait-for-loop-to-finish-node-js/nodejs_wait_for_loop_to_finish.jpg)