我在Node.js中有一个函数,它接受一个数组并循环遍历它,对每个元素进行一些耗时的计算。
这是函数的超简化版本:
var analyze_data = function (data) {
data.forEach(function (elm) {
if (elm.myProp == true) {
return true;
}
});
return false;
}
基本上,我希望函数返回true,如果任何元素' property myProp
等于true。如果所有元素都不满足此条件,则该函数应返回false。
但是,代码永远不会等待forEach循环完成。换句话说,如果数组中的第100个元素满足条件,则该函数应返回true。相反,它跳到return false;
并在forEach
循环有时间结束之前返回false。
有解决方法吗?
所以我意识到我过度简化了我的问题 - 我实际上使用的是Node.js package es6-promise,我的代码看起来更像是这样:
var analyze_data = function (data) {
return new Promise(function (resolve, reject) {
data.forEach(function (elm) {
if (elm.myProp == true) {
resolve(elm);
}
});
resolve(false);
});
}
所以实际上,我没有在forEach函数中返回值而不是外部函数的问题。另外,请注意函数如何解析为元素本身而不是true,否则为false。我实际上想要返回一些相关数据,如果其中一个元素通过条件,否则返回false表示它们都失败了。
现在有什么想法吗? :p另外,感谢所有原始答案!
答案 0 :(得分:6)
这不是同步/异步执行的问题。你正在做的是在每个回调中返回true(对于你的analyze_data
函数是不可见的),然后在forEach完成后返回false。
您需要使用Array.prototype.some
:
var analyze_data = function (data) {
return data.some(function (elm) {
return elm.myProp == true;
});
}
答案 1 :(得分:4)
你的问题不在于forEach是异步的,因为它不是。但是因为你把一个回报误认为另一回事。
您从回调中返回true
而非主要功能。
forEach调用forEach因为它对数组中的每个元素执行,所以你不能在中间停止。以下是documentation的摘录:
注意:无法停止或中断forEach循环。解决方案是 使用Array.every或Array.some。
答案 2 :(得分:2)
问题是您从内部函数返回true值,但未在外部函数中捕获它。如果你这样做它应该工作:
var retVal = false;
data.forEach(function (elm) {
if (elm.myProp == true) {
retVal = true;
}
});
return retVal;
现在你有两个功能:
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)
}
编辑:
data.forEach(function (elm) {
if (elm.myProp == true) {
resolve(elm);
}
});
resolve(false);
你现在(可能)解析为elm
,但总是在解析为false
之后。我对这种行为并不是100%肯定,但我猜想后者会覆盖第一个。所以,你需要检查:
is_found = false;
data.forEach(function (elm) {
if (elm.myProp == true) {
resolve(elm);
is_found = true;
}
});
if (!is_found) {
resolve(false);
}
当然,看起来你应该这样做:
if (!is_found) {
reject(false);
}
那么你可以这样做:
promise.then(function(result) {
// do stuff since it found stuff :)
}, function(err) {
// do stuff since if didn't find anything :(
});