Synchronous forEach loop (wait for it to end)
Solution 1
It is not a question of sync/async execution. What you are doing is returning true in the for each callback (which is invisible for your analyze_data
function), then returning false after forEach is finished.
You need to use Array.prototype.some
:
var analyze_data = function (data) {
return data.some(function (elm) {
return elm.myProp == true;
});
}
Solution 2
Your problem is not the fact that forEach is async, because it is not. But because you mistake one return for another.
You return true
from callback not from your main function.
forEach called forEach because it executes for each element on the array, you can't stop in the middle. Here is the excerpt from documentation:
Note: There is no way to stop or break a forEach loop. The solution is to use Array.every or Array.some.
Solution 3
The issue is that you are returning from your inner function the value of true, but not capturing it in the outer function. If you do it like this it should work:
var retVal = false;
data.forEach(function (elm) {
if (elm.myProp == true) {
retVal = true;
}
});
return retVal;
Right now you have two functions:
var analyze_data = ***function (data)*** {
data.forEach(***function (elm)*** {
if (elm.myProp == true) {
return true; //returns out of function(elm)
}
});
//the true value is gone - you didn't do anything with it
return false; //always returns false out of function(data)
}
EDIT:
data.forEach(function (elm) {
if (elm.myProp == true) {
resolve(elm);
}
});
resolve(false);
You now are (possibly) resolving to elm
, but ALWAYS after that resolving to false
. I'm not 100% sure on the behaviour, but I would guess that the later one overwrites the first one. So again, you need to check:
is_found = false;
data.forEach(function (elm) {
if (elm.myProp == true) {
resolve(elm);
is_found = true;
}
});
if (!is_found) {
resolve(false);
}
Of course, it kind of seems like you should be doing:
if (!is_found) {
reject(false);
}
So then you can do:
promise.then(function(result) {
// do stuff since it found stuff :)
}, function(err) {
// do stuff since if didn't find anything :(
});
apparatix
Updated on July 09, 2022Comments
-
apparatix almost 2 years
I have a function in Node.js that takes in an array and loops through it, doing somewhat time-consuming computations on each element.
Here's a super-simplified version of the function:
var analyze_data = function (data) { data.forEach(function (elm) { if (elm.myProp == true) { return true; } }); return false; }
Essentially, I want the function to return true if any of the elements' property
myProp
is equal to true. If none of the elements satisfy this condition, the function should return false.However, the code never waits for the forEach loop to finish. In other words, if the 100th element in the array satisfies the condition, the function should return true. Instead, it skips to
return false;
and returns false before theforEach
loop has time to finish.Is there a solution to this?
Edit
So I realized that I oversimplified my question - I'm actually using the Node.js package es6-promise, and my code looks more like this:
var analyze_data = function (data) { return new Promise(function (resolve, reject) { data.forEach(function (elm) { if (elm.myProp == true) { resolve(elm); } }); resolve(false); }); }
So in reality, I don't have the issue of returning a value in the forEach function rather than the outer function. Additionally, notice how the function resolves to the element itself rather than true, otherwise false. I actually want to return some relevant data if the one of the elements passes the condition, otherwise false to indicate that they all failed.
Any ideas now? :p Also, thanks for all the original answers!