对于如何最好地写这个有点困惑 - 希望这个描述很清楚。
我有一个forEach函数,我在其中浏览一些JS对象数据,并为每个项目执行一个函数:
found.forEach(function(item) {
processData(item['userID']);
});
在这个processData
函数中,我正在使用MongoDB find()调用。
var processData = function(userIDSelected) {
User.find( {_id: userIDSelected},
{gender: 1, country:1}, function(req, foundUser) {
processUserInfo(foundUser[0]['gender']);
});
}
我遇到的问题是,如果考虑到每个呼叫将依次运行processUserInfo
,我如何等待forEach中的所有内容完成。
我已经看过使用Q库和Q.all然而这不起作用。
是否有Q函数等待长链中的所有内容完成?
由于
答案 0 :(得分:1)
返回一个使用包含每个承诺的履行价值的数组来履行的承诺,或者被拒绝的拒绝理由与第一个被拒绝的承诺相同。
返回使用一系列承诺状态快照实现的承诺,但仅在所有原始承诺已经解决后,即变为满足或被拒绝。
所以你要做三件事:
修改processData
以及可能调用MongoDB,以便最终返回processData
返回异步操作的承诺。 (道歉,我不熟悉MongoDB。Alnitak says对于现代版本,如果你不提供回调,MongoDB会返回一个promise(很好!)。否则,this question and its answers may help返回一个promise对于基于回调的API。)
使用map
代替forEach
获取所产生承诺的数组。
在该承诺数组上使用Q.all
或Q.allSettled
。
如果User.find
在未指定回调的情况下返回承诺,则#1看起来某事,如下所示:
var processData = function(userIDSelected) {
return User.find(
{_id: userIDSelected},
{gender: 1, country:1}
).then(function(req, foundUser) { // <== Check these args with the MongoDB docs!
return processUserInfo(foundUser[0]['gender']);
});
};
如果没有,您可以使用Q.defer
:
var processData = function(userIDSelected) {
var d = Q.defer();
User.find(
{_id: userIDSelected},
{gender: 1, country:1},
function(req, foundUser) {
processUserInfo(foundUser[0]['gender']);
d.resolve(/*...data could go here...*/); // You'd use d.reject() if there were an error
});
return d.promise;
};
然后这是2和3的样子:
Q.all(found.map(function(item) { // Or Q.allSettled
return processData(item);
}))
.then(...)
.catch(...);
如果processData
仅使用其第一个参数(忽略任何额外的参数),则可以抛弃中间函数:
Q.all(found.map(processData)) { // Or Q.allSettled
.then(...)
.catch(...);
...但仅如果processData
忽略了额外的参数,因为map
将传递三个(值,其索引和数组)。
答案 1 :(得分:0)