将 q.all 正确放置在 array.map 和 _.forEach 中
Proper placement of q.all inside array.map with _.forEach
我有以下代码,它使用 find()
使用 array.map
提取的值搜索我的 mongodb。表示搜索returns一个对象,然后我用_.forEach
来提取值。
我使用 this article 作为基础,但是他的示例和我的示例之间的区别在于他只使用了一个循环。我正在使用两个。在这种情况下,我应该把我的 q.all()
?
放在哪里?
这是我的代码。 请注意是服务器端:
'use strict';
var q = require('q');
exports.downloadEmployee = function (req, res) {
var tempCtr = [];
if (req.params.hasdr === "yes") {
return queries.generateDirectReportsCSV(req.params.id).then(function (directReports) {
return directReports;
}).then(function (directReports) {
var empIDcoll = _.pluck(directReports.Data, "employeenumber");
return empIDcoll;
}).then(function (empIDcoll) {
var promises = [];
empIDcoll.map(function (id) {
return EmployeeInfo.find({ employeeID: id }, function (err, results) {
if (err) { return err; }
_.forEach(results, function (item) {
if (item) {
tempCtr.push({
employeeID: item.employeeID,
employeeName: item.employeeName
});
promises.push(tempCtr);
}
});
});
q.all(promises).then(function (results) {
return res.json(results);
});
});
});
}
当我 运行 这样做时,我没有得到任何结果。
任何答案将不胜感激。
谢谢。
更新: 我决定修改我的代码并将 array.map
替换为通常的 for loop
:
.then(function (empIDcoll) {
for (var i = 0; i <= empIDcoll.length - 1; i++) {
var promise = EmployeeInfo.find({ employeeID: empIDcoll[i] }, function (err, results) {
if (err) { return err; }
_.forEach(results, function (item) {
if (item) {
tempCtr.push({
employeeID: item.employeeID,
employeeName: item.employeeName,
currentShift: item.currentShift,
isOpenToIntlAssignment: item.isOpenToIntlAssignment,
desiredRole1: item.desiredRole1,
desiredRole2: item.desiredRole2,
desiredRole3: item.desiredRole3,
desiredRoleOther: item.desiredRoleOther,
passportInfo: item.passportInfo,
visaInfo: item.visaInfo,
yrsInIT: item.yrsInIT,
yrsAsCustomerPM: item.yrsAsCustomerPM,
yrsAsCustomerProgM: item.yrsAsCustomerProgM,
primaryDomain: item.primaryDomain,
primaryDomainOther: item.primaryDomainOther,
primaryIndustry: item.primaryIndustry,
primaryIndustryOther: item.primaryIndustryOther,
isPMPCertified: item.isPMPCertified,
pmpCertExpiryDate: item.pmpCertExpiryDate,
isPGMPCertified: item.isPGMPCertified,
pgmpCertExpiryDate: item.pgmpCertExpiryDate,
isScrumCertified: item.isScrumCertified,
scrumCertExpiryDate: item.scrumCertExpiryDate,
biggestProjectTCV: item.biggestProjectTCV,
biggestTeamSizeManaged: item.biggestTeamSizeManaged,
avgTeamSizeManaged: item.avgTeamSizeManaged,
biggestBilledFTE: item.biggestBilledFTE,
avgBilledFTE: item.avgBilledFTE
});
}
});
});
promises.push(promise);
}
return q.all(promises).then(function(data){
return res.json(data);
});
});
...但它仍然没有返回任何内容。我做错了什么?
删除EmployeeInfo.find
之前的return
语句?
看看,
var promises = questions.map(function(question) {
return $http({
url : 'upload/question',
method: 'POST',
data : question
});
});
return $q.all(promises);
第一次几乎正确!
当你这样做的时候:
var promises = [];
empIDcoll.map(function (id) {
return EmployeeInfo.find({ employeeID: id }, function (err, results) {
if (err) { return err; }
_.forEach(results, function (item) {
if (item) {
tempCtr.push({
employeeID: item.employeeID,
employeeName: item.employeeName
});
promises.push(tempCtr);
}
});
});
q.all(promises).then(function (results) {
return res.json(results);
});
});
您的 q.all
位置错误(在 .map
内);并且您将 objects 推入 promises
数组,而不是实际的 promises。尝试做类似的事情:
// Here, we will build an array of promises by transforming each element of `empIDcoll` to a promise (via `.map`).
var promises = empIDcoll.map(function (id) {
return EmployeeInfo.find({ employeeID: id }).exec(); // I assume that .exec() will return a promise.
});
q.all(promises).then(function (results) { // `results` will be an array, each element will contain the result of each promise pushed to `promises`.
return res.json(results);
});
试试这个。这可能需要一些调整(让我们知道),因为我真的不知道您的应用程序/模型的结构。
我的第一个建议是首先停止循环访问 employeeId。
你可以像这样使用 mongoDB 的 $in 运算符
EmployeeInfo.find({ employeeID: {$in: empIDcoll} }, function (err, results) {
if(err) {
//handle error
return err;
}
res.json(results);
});
但由于我不了解您的应用程序,所以我真的无法判断您是否想要循环访问 empIdColl。
遍历 empIdColl
现在我不确定您的 monogdb 查询是否会return 承诺,所以为了安全起见,我假设它不会
var promises = empIDcoll.map(function (id) {
var singleDefer = q.defer(); //create a deferred object which has promise in it
EmployeeInfo.find({ employeeID: id }, function(err, results) {
if(err) {
return singleDefer.reject(err);
}
return singleDefer.resolve(results); //resolve whole array
});
return singleDefer.promise;
});
q.all(promises)
.then(function (arrayOfResults) {
var responseData = [];
arrayOfResuls.forEach(function(results) {
results.forEach(function(individualResult) {
if(individualResult) {
responseData.push({
employeeID: item.employeeID,
...
...
avgBilledFTE: item.avgBilledFTE
});
}
});
});
return res.json(responseData);
})
.catch(function(err) {
//handle error
});
我在这里发布我的工作解决方案,以供将来可能遇到相同问题的人使用。感谢 SinDeus 提供简单明了的解决方案。 :)
.then(function (empIDcoll) {
// push user's employee number in first row
empIDcoll.unshift(req.params.id);
// return resolved promises from EmployeeInfo.find()
// this will return user's direct reports' information (if any)
var promises = empIDcoll.map(function (id) {
return EmployeeInfo.find({ employeeID: id }).exec();
});
// Take resolved promises from above statement and iterate to get final results.
q.all(promises).then(function (results) {
_.forEach(results, function (item) {
var len = item.length - 1;
if (len >= 0) {
tempCtr.push({
employeeID: item[0].employeeID,
employeeName: item[0].employeeName
// ... other fields here ...
});
}
});
return res.json(tempCtr);
});
});
}
我有以下代码,它使用 find()
使用 array.map
提取的值搜索我的 mongodb。表示搜索returns一个对象,然后我用_.forEach
来提取值。
我使用 this article 作为基础,但是他的示例和我的示例之间的区别在于他只使用了一个循环。我正在使用两个。在这种情况下,我应该把我的 q.all()
?
这是我的代码。 请注意是服务器端:
'use strict';
var q = require('q');
exports.downloadEmployee = function (req, res) {
var tempCtr = [];
if (req.params.hasdr === "yes") {
return queries.generateDirectReportsCSV(req.params.id).then(function (directReports) {
return directReports;
}).then(function (directReports) {
var empIDcoll = _.pluck(directReports.Data, "employeenumber");
return empIDcoll;
}).then(function (empIDcoll) {
var promises = [];
empIDcoll.map(function (id) {
return EmployeeInfo.find({ employeeID: id }, function (err, results) {
if (err) { return err; }
_.forEach(results, function (item) {
if (item) {
tempCtr.push({
employeeID: item.employeeID,
employeeName: item.employeeName
});
promises.push(tempCtr);
}
});
});
q.all(promises).then(function (results) {
return res.json(results);
});
});
});
}
当我 运行 这样做时,我没有得到任何结果。
任何答案将不胜感激。
谢谢。
更新: 我决定修改我的代码并将 array.map
替换为通常的 for loop
:
.then(function (empIDcoll) {
for (var i = 0; i <= empIDcoll.length - 1; i++) {
var promise = EmployeeInfo.find({ employeeID: empIDcoll[i] }, function (err, results) {
if (err) { return err; }
_.forEach(results, function (item) {
if (item) {
tempCtr.push({
employeeID: item.employeeID,
employeeName: item.employeeName,
currentShift: item.currentShift,
isOpenToIntlAssignment: item.isOpenToIntlAssignment,
desiredRole1: item.desiredRole1,
desiredRole2: item.desiredRole2,
desiredRole3: item.desiredRole3,
desiredRoleOther: item.desiredRoleOther,
passportInfo: item.passportInfo,
visaInfo: item.visaInfo,
yrsInIT: item.yrsInIT,
yrsAsCustomerPM: item.yrsAsCustomerPM,
yrsAsCustomerProgM: item.yrsAsCustomerProgM,
primaryDomain: item.primaryDomain,
primaryDomainOther: item.primaryDomainOther,
primaryIndustry: item.primaryIndustry,
primaryIndustryOther: item.primaryIndustryOther,
isPMPCertified: item.isPMPCertified,
pmpCertExpiryDate: item.pmpCertExpiryDate,
isPGMPCertified: item.isPGMPCertified,
pgmpCertExpiryDate: item.pgmpCertExpiryDate,
isScrumCertified: item.isScrumCertified,
scrumCertExpiryDate: item.scrumCertExpiryDate,
biggestProjectTCV: item.biggestProjectTCV,
biggestTeamSizeManaged: item.biggestTeamSizeManaged,
avgTeamSizeManaged: item.avgTeamSizeManaged,
biggestBilledFTE: item.biggestBilledFTE,
avgBilledFTE: item.avgBilledFTE
});
}
});
});
promises.push(promise);
}
return q.all(promises).then(function(data){
return res.json(data);
});
});
...但它仍然没有返回任何内容。我做错了什么?
删除EmployeeInfo.find
之前的return
语句?
看看,
var promises = questions.map(function(question) {
return $http({
url : 'upload/question',
method: 'POST',
data : question
});
});
return $q.all(promises);
第一次几乎正确!
当你这样做的时候:
var promises = [];
empIDcoll.map(function (id) {
return EmployeeInfo.find({ employeeID: id }, function (err, results) {
if (err) { return err; }
_.forEach(results, function (item) {
if (item) {
tempCtr.push({
employeeID: item.employeeID,
employeeName: item.employeeName
});
promises.push(tempCtr);
}
});
});
q.all(promises).then(function (results) {
return res.json(results);
});
});
您的 q.all
位置错误(在 .map
内);并且您将 objects 推入 promises
数组,而不是实际的 promises。尝试做类似的事情:
// Here, we will build an array of promises by transforming each element of `empIDcoll` to a promise (via `.map`).
var promises = empIDcoll.map(function (id) {
return EmployeeInfo.find({ employeeID: id }).exec(); // I assume that .exec() will return a promise.
});
q.all(promises).then(function (results) { // `results` will be an array, each element will contain the result of each promise pushed to `promises`.
return res.json(results);
});
试试这个。这可能需要一些调整(让我们知道),因为我真的不知道您的应用程序/模型的结构。
我的第一个建议是首先停止循环访问 employeeId。 你可以像这样使用 mongoDB 的 $in 运算符
EmployeeInfo.find({ employeeID: {$in: empIDcoll} }, function (err, results) {
if(err) {
//handle error
return err;
}
res.json(results);
});
但由于我不了解您的应用程序,所以我真的无法判断您是否想要循环访问 empIdColl。
遍历 empIdColl
现在我不确定您的 monogdb 查询是否会return 承诺,所以为了安全起见,我假设它不会
var promises = empIDcoll.map(function (id) {
var singleDefer = q.defer(); //create a deferred object which has promise in it
EmployeeInfo.find({ employeeID: id }, function(err, results) {
if(err) {
return singleDefer.reject(err);
}
return singleDefer.resolve(results); //resolve whole array
});
return singleDefer.promise;
});
q.all(promises)
.then(function (arrayOfResults) {
var responseData = [];
arrayOfResuls.forEach(function(results) {
results.forEach(function(individualResult) {
if(individualResult) {
responseData.push({
employeeID: item.employeeID,
...
...
avgBilledFTE: item.avgBilledFTE
});
}
});
});
return res.json(responseData);
})
.catch(function(err) {
//handle error
});
我在这里发布我的工作解决方案,以供将来可能遇到相同问题的人使用。感谢 SinDeus 提供简单明了的解决方案。 :)
.then(function (empIDcoll) {
// push user's employee number in first row
empIDcoll.unshift(req.params.id);
// return resolved promises from EmployeeInfo.find()
// this will return user's direct reports' information (if any)
var promises = empIDcoll.map(function (id) {
return EmployeeInfo.find({ employeeID: id }).exec();
});
// Take resolved promises from above statement and iterate to get final results.
q.all(promises).then(function (results) {
_.forEach(results, function (item) {
var len = item.length - 1;
if (len >= 0) {
tempCtr.push({
employeeID: item[0].employeeID,
employeeName: item[0].employeeName
// ... other fields here ...
});
}
});
return res.json(tempCtr);
});
});
}