我的问题是如何在 Node Js 中编写嵌套循环
我的代码是
var result = db.data;
var FirstArray= new Array();
var SecondArray= new Array();
GetUserData();
async function GetUserData(){
for (let info of result) {
await getUserInfo(info);
}
res.send({status:"True", data: FirstArray, newdata:SecondArray });
}
function getUserInfo(info){
return new Promise(( resolve, reject )=>{
UserModel.UserType.findOne({'_id': info.UserId }, usersProjection, function(err, UserData) {
if(err) {
res.send({status:"Fale", Error:err });
reject(err);
} else {
var data = UserData;
FirstArray.push(data);
GetUser();
async function GetUser(){
for (let newinfo of data ) {
await getnewUserInfo(newinfo);
}
}
function getnewUserInfo(newinfo){
return new Promise(( resolve, reject )=>{
UserModel.UserTypeNew.findOne({'_id': newinfo.UserId }, usersProjection, function(newerr, UserData) {
if(newerr) {
res.send({status:"Fale", Error:newerr });
reject(err);
} else {
SecondArray.push(UserData)
resolve();
}
});
});
}
}
});
});
}
我将仅获取第一个循环详细信息如何获取第二个循环详细信息。
还建议其他方法。
那么哪种方法是嵌套循环的最佳实践。
最佳答案
由于 Mongoose 应该返回 promise ,因此您不需要新的 promise 。您可以使用 map 将数据映射到 Promise,然后使用 Promise.all 等待它们同时执行。您当前的代码将逐个执行查询(仅当当前代码完成时才执行下一个查询)。这是不需要的并且非常慢。
因此您可以将 db.data
映射到 [[first,second],[first,second],...]
。我不映射 findOne
的结果,因为它不应该返回一个数组,并且觉得很奇怪 resultOfFindOne
的某些内容实际上有效,因为 findOne 应该返回一个文档或 null。
UserModel.UserType.findOne
和 UserModel.UserTypeNew.findOne
都尝试通过 _id
查找一条记录,并且都使用相同的 _id
,因此不需要执行 UserType 查询,然后当返回执行 UserTypeNew 查询时,您只需使用 info.UserId
进行这两个查询。
const GetUserData = (result) =>
Promise.all(
result.map(info=>getUserInfo(info))
).then(
results=>{//results should be [[first,second],[first,second],...]
let [FirstArray,SecondArray] = results.reduce(
([allFirst,allSecond],[first,second])=>
[allFirst.concat([first]),allSecond.concat([second])],
[[],[]]
);
res.send({ status: "True", data: FirstArray, newdata: SecondArray })
}
).catch(
err=>
res.send({status:"Fale", Error:err })
);
const getUserInfo = info =>
//mongoose can return promises, no need to convert callback api to promise:
//http://mongoosejs.com/docs/queries.html
Promise.all([
UserModel.UserType.findOne({ '_id': info.UserId }, usersProjection).exec(),
UserModel.UserTypeNew.findOne({ '_id': info.UserId }, usersProjection).exec()
]);
//when using const the function is not hoisted so you can't call a function
// before it was declared.
GetUserData(db.data);
如果您使用的是旧版本的 mongoose(不是 5.xxx),您可能仍然需要将基于回调的 api 转换为 Promise,它看起来有点像这样:
const asPromise = object => fn => args =>
new Promise(
(resolve,reject)=>
fn.apply(
object,
args.concat([
(...result)=>
(result[0])//first argument of callback is error
? reject(result[0])//reject with error
: resolve(result.slice(1,result.length))//resolve with result(s)
])
)
);
const newUserType = asPromise(UserModel.UserTypeNew);
const userType = asPromise(UserModel.UserType);
//making a query with callback but convert it to promise
newUserType(UserModel.UserTypeNew.findOne)([
{ '_id': info.UserId }, usersProjection
]).then(//this will resolve as array, only need first item
([result])=>result
);
userType(UserModel.UserType.findOne)([//note that I'm not passing UserModel.UserTypeNew.findOne
{ '_id': info.UserId }, usersProjection
]).then(//this will resolve as array, only need first item
([result])=>result
);
关于javascript - Node js 异步和等待的嵌套循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48592155/