Reputation: 279
I have a for loop in which each iteration runs a promise and adds the index of the promise to the array if the promise is resolved, and in the end, I want to output the resulted array. However, the function keeps returning the array before completing all the promises in the for loop. As a result, I always get an empty returned array.
My code looks like this:
var str_list = [some strings];
let myFunction = () => {
var array = [];
for (i = 0; i < length; i++) {
new Promise((resolve, reject) => {
if (str_list[i] fulfills some conditions) {
resolve();
} else {
reject(
throw new Error())
}
}).then(() => {
array.push(i);
}).catch((err) => {
console.log(i, err);
});
}
return array;
}
Is there a good way to wait for the for loop to complete before returning the value?
Upvotes: 3
Views: 4691
Reputation: 6981
var str_list = ["..."];
let myFunction = async () =>
{
const promises = [];
for (i = 0; i < length; i++)
{
promises.push(new Promise((resolve, reject) =>
{
const condition = // ...
resolve(condition ? str_list[i] : false);
}));
}
return (await Promise.all(promises)).filter(f => f !== false);
}
Try this. Essentially, what it does is that it adds all of the Promises to an array, and then calls Promise.all
on them, which executes them in parallel and waits for all of them to finish.
The results are then returned in order, those results being what was passed into the resolve()
function in each Promise
, and will be either str_list[i]
or false
. Then, the call to filter()
removes all of the entries that are false
.
If you care about being concise, then this can be greatly simplified:
var str_list = ["..."];
let myFunction = async () =>
{
const promises = str_list.map(async (value, index) => condition ? value : false);
return (await Promise.all(promises)).filter(f => f !== false);
}
This code works the same way as the first snippet; it's just much shorter.
I made the method async
because there is no way to return the results of a Promise
without await
ing it. If you don't want to use an async
method, you can either return a Promise
, which you can then wait on with await
or .then()
:
var str_list = ["..."];
let myFunction = () => {
const promises = [];
for (i = 0; i < length; i++) {
promises.push(new Promise((resolve, reject) => {
const condition = // ...
resolve(condition ? str_list[i] : false);
}));
}
return Promise.all(promises).then(strs => strs.filter(f => f !== false));
}
// myFunction().then(results => ...)
Or you can use a callback:
var str_list = ["..."];
let myFunction = (callback) =>
{
const promises = [];
for (i = 0; i < length; i++)
{
promises.push(new Promise((resolve, reject) =>
{
const condition = // ...
resolve(condition ? str_list[i] : false);
}));
}
return Promise.all(promises).then(results => callback(results.filter(f => f !== false));
}
// myFunction(results => ...);
Upvotes: 2