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:
const callbackFunc = (param1, param2, callback) => {
setTimeout(() => callback('Ok'), 1000)
}
let t = []
const test = ['1', '2'];
const promises = [];
for(let i in test) {
promises.push(new Promise(resolve => {
callbackFunc(2, test[i], result => {
resolve(result)
})
}))
}
Promise.all(promises)
.then(result => {
t = result;
console.log(t);
})
Related Topics
How to Export or Convert Json to Excel in Angularjs
When Click on Menu, It Opens, When Click Again It Close
Javascript Random on Array Without Repeat
How to Listen to the Window Scroll Event in a Vuejs Component
How to Add Disable Option or Default Option in Select Box
Jquery Ajax Readystate 0 Responsetext Status 0 Statustext Error
Javascript Passing Element Id as Argument
Owl Carousel, Navigation Disabled After Reaching First/Last Item
Exclude Weekends in JavaScript Date Calculation
How to Hide Code from Cells in Ipython Notebook Visualized With Nbviewer
Regex to Replace Multiple Spaces With a Single Space
Javascript: Check If Page Is At the Top
Slick.Js: Get Current and Total Slides (Ie. 3/5)
How to Check Whether Dynamically Attached Event Listener Exists or Not
Programmatically Disabling Chrome Auto-Fill
Get Selected Value from Multiple Select on Change in Dynamic Form