Javascript Loop Wait Until API Call Finished

How to wait in loop till the series of API calls one inside another is completed in Javascript

Please note that asynchronous functions (both .then() & async/await) won't work inside forEach
ALSO .then() approach won't work in neither forEach or for loops.

To run an asynchronous function inside a loop you need to use the async/await approach inside either a for loop or a Recursion Function.

In the following example, we're gonna use the async/await approach inside a for loop.

const list = ['firstItem', 'secondeItem', 'lastItem'];

// First method
// use `i` parameter to check in which index the method was called
function methodOne(i: string): Promise<void> {
return new Promise((resolve) => {
setTimeout(() => {
console.log(`Make the first API call at index ${i}`);
resolve();
}, 1000);
});
}


// Second method
// use `i` parameter to check in which index the method was called
function methodTwo(i: string): Promise<void> {
return new Promise((resolve) => {
setTimeout(() => {
console.log(`Make the second API call at index ${i}`);
resolve();
}, 1000);
});
}

// run both methods sequentially inside a `for` loop
async function runMethodOneAndMethodTwoInsideLoop (): Promise<void> {
for (let i in list) {
await methodOne(i);
await methodTwo(i);
}
}

runMethodOneAndMethodTwoInsideLoop();

To call methodTwo inside methodOne (which I don't recommend) you can use the following example.

const list = ['firstItem', 'secondeItem', 'lastItem'];

// First method
// use `i` parameter to check in which index the method was called
function methodOne(i: string): Promise<void> {
return new Promise((resolve) => {
setTimeout(async () => {
console.log(`Make the first API call at index ${i}`);
await methodTwo(i);
resolve();
}, 1000);
});
}


// Second method
// use `i` parameter to check in which index the method was called
function methodTwo(i: string): Promise<void> {
return new Promise((resolve) => {
setTimeout(() => {
console.log(`Make the second API call at index ${i}`);
resolve();
}, 1000);
});
}

// run only `methodOne` inside a `for` loop since `methodTwo` will be called inside `methodOne`
async function runMethodOneInsideLoop(): Promise<void> {
for (let i in list) {
await methodOne(i);
}
}

runMethodOneInsideLoop();

To learn more about asynchronous functions and how to use them inside loops check out this gist I created.

How to wait for the final result of a for loop with API calls?

You can make this function return a promise and await the function (as long as your function is an async function)

const gotPeeps = () => {
return new Promise((resolve, reject) => {
const peepsList = []; // declare the empty array to e filled

challongeClient.tournaments.show({
id: tournamentURL,
callback: (err, data) => {
for (const [key, value] of Object.entries(data.tournament.matches)) {
if (value.match.state === "open") {
peepsList.push(value.match.player1Id, value.match.player2Id);
}
}
resolve(peepsList); // resolve the promise with the filled array
// TODO: handle reject
},
});
})
};

(async () => {
try {
const result = await gotPeeps();
} catch (error) {
// TODO: handle error
}
})();

For loop to call API function and wait for it

This starts a bunch of asynchronous operations in parallel. I assume that's not what you want, and you want to wait for one to actually finish before starting the next one.

It's easiest if you can use async/await syntax:

async saveMyData() {
for (const element of this.elements) {
try {
const response = await CALL_MY_API.read(element)
// do something with response
} catch (error) {
this.showError(error)
}
}
}

If you can't, you'll need to chain the promises manually:

saveMyData() {
// Start with an immediately resolved promise.
let promise = new Promise((resolve, reject) => resolve())
// Add each element to the chain.
this.elements.forEach(element => {
promise = promise.then(() => {
return CALL_MY_API.read(element)
.then(response => {
// do something with response
})
.catch(error => {
this.showError(error)
})
})
})
}

How do i make javascript loop wait for each iteration of loop to finish before starting the next?

If you want to stick with the ES5 way of handling Promises, you could use the following approach:

const start = console.log(Date.now())

// Create a instantly resolved promise
for (let i = 0, p = Promise.resolve(); i < 1000; i++) {
// append new promise to the chain
p = p.then(() => request()
.then(() => console.log(Date.now() - start));
}

If you can use ES6 methods, you could write this using the async/await pattern like so:

const asyncLoop = async () => {
const start = console.log(Date.now())

for (let i = 0; i < 1000; i++) {
const data = await request();
console.log(Date.now() - start);
}
}

asyncLoop();

The chance that you really want to make the requests one after the other is actually pretty small though, so in case you want to make the request simultaneously, but do something after all of them resolved, you can use Promise.all(...)

const start = console.log(Date.now())
const requests = [request1, request2, ...];

Promise.all(requests)
.then(() => console.log(Date.now() - start));

Wait for the for loop to complete and then return the value

Here is how to rewrite your specific code to accomplish what you're trying to accomplish: