2014-10-31 86 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; 
    }); 
}