2014-10-31 70 views
4

我在Node.js中有一个函数,它接受一个数组并在其中循环,对每个元素进行一些耗时的计算。Synchronous forEach循环(等待它结束)

这里的功能的超级简化版:

var analyze_data = function (data) { 
    data.forEach(function (elm) { 
     if (elm.myProp == true) { 
      return true; 
     } 
    }); 
    return false; 
} 

从本质上讲,我希望函数,如果任何元素的属性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函数中的值而不是外部函数的问题。此外,请注意函数如何解析为元素本身而不是真,否则为false。如果其中一个元素通过了条件,我实际上想要返回一些相关数据,否则返回false以表明它们全部失败。

现在有什么想法? :p另外,感谢所有原始答案!

+0

如果切换到诺言,你可以用'Q.all',例如。 https://github.com/kriskowal/q/wiki/API-Reference#promiseall – akonsu 2014-10-31 15:43:08

+0

你只是在错误的地方返回真值,试着使用'Array.prototype.some' – micnic 2014-10-31 15:47:52

回答

1

问题是,你从内函数返回的值为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。我对这种行为并不十分确定,但我猜想后面的一个会覆盖第一个。如此反复,你需要检查:

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 :(
}); 
+0

据我所知,问题是这些功能是异步的。帖子中的代码仅仅是一个例子。 – akonsu 2014-10-31 15:45:20

+1

可能的是,我的理解是他**认为**这是问题,但考虑到这个例子,它似乎更可能仅仅是不捕获返回值 – dave 2014-10-31 15:48:00

+0

@dave如果你看看编辑I只是做了,似乎该函数只是返回false而不等待forEach循环完成迭代 – apparatix 2014-11-04 20:39:17

4

你的问题并不是说forEach是异步的,因为它不是。但是因为你把一个回报误认为另一回。

您从回调中返回true而不是从主函数返回。

forEach for eachach因为它执行数组上的每个元素,所以不能停在中间。这里是从documentation摘录:

注意:没有办法停止或破坏forEach循环。解决方案是 以使用Array.every或Array.some。

5

这不是同步/异步执行的问题。你正在做的是在每个回调中返回true(这对你的analyze_data函数是不可见的),然后在forEach完成后返回false。

您需要使用Array.prototype.some

var analyze_data = function (data) { 
    return data.some(function (elm) { 
     return elm.myProp == true; 
    }); 
}