Reputation: 4285
My Question is How To Write Nested Loops In Node Js
My Code Is
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();
}
});
});
}
}
});
});
}
I will Get The First Loop Details Only How to Get Second Loop Details.
suggest Another Methods also.
Then which method is the best practice of nested loops.
Upvotes: 1
Views: 1927
Reputation: 4285
exports.GetPostList = function (req, res) {
var SkipCoun = 0;
SkipCoun = parseInt(req.params.Limit) * 10;
QuestionsPostModel.QuestionsPostType.find({}, {}, { sort: { createdAt: -1 }, skip: SkipCoun, limit: 10 }, function (err, result) {
if (err) {
res.status(500).send({ status: "False", message: "Some error occurred while Find Following Users ." });
} else {
const GetUserData = (result) =>
Promise.all(
result.map(info => getPostInfo(info))
).then( result =>{ console.log(result); res.send({ status: "True", data: result }) }
).catch(err => res.send({ status: "False", Error: err }));
const getPostInfo = info =>
Promise.all([
UserModel.UserType.findOne({ '_id': info.UserId }, usersProjection).exec(),
FollowModel.FollowUserType.count({ 'UserId': info.UserId }).exec(),
RatingModel.QuestionsRating.count({ 'PostId': info._id, 'ActiveStates': 'Active' }).exec(),
RatingModel.QuestionsRating.count({ 'UserId': req.params.UserId, 'PostId': info._id, 'PostUserId': info.UserId, 'ActiveStates': 'Active' }).exec(),
AnswerModel.QuestionsAnwer.count({ 'PostId': info._id, 'ActiveStates': 'Active' }).exec(),
AnswerModel.QuestionsAnwer.find({ 'PostId': info._id }, 'AnswerText UserId Date').exec()
]).then(data => {
let UserData = data[0];
let followCount = data[1];
let ratingCount = data[2];
let UserRating = data[3];
let AnswerCount = data[4];
let Answerdata = data[5];
var AnswersArray= new Array();
return GetAnsUserData();
async function GetAnsUserData(){
for (let ansInfo of Answerdata) {
await getAnswerInfo(ansInfo);
}
let result = {
_id: info._id,
UserId: UserData._id,
UserName: UserData.UserName,
UserCategoryId: UserData.UserCategoryId,
UserCategoryName: UserData.UserCategoryName,
UserImage: UserData.UserImage,
UserCompany: UserData.UserCompany,
UserProfession: UserData.UserProfession,
Followers:followCount,
PostTopicId: info.PostTopicId,
PostTopicName: info.PostTopicName,
PostDate: info.PostDate,
PostText: info.PostText ,
PostLink: info.PostLink,
PostImage: info.PostImage,
PostVideo: info.PostVideo,
RatingCount: ratingCount,
UserRating: UserRating,
AnswersCount: AnswerCount,
Answers: AnswersArray,
};
return result;
}
function getAnswerInfo(ansInfo){
return new Promise(( resolve, reject )=>{
UserModel.UserType.findOne({'_id': ansInfo.UserId }, usersProjection, function(err, AnsUserData) {
if(err) {
res.send({status:"Fale", Error:err });
reject(err);
} else {
FollowModel.FollowUserType.count({'UserId': AnsUserData._id}, function(newerr, count) {
if(newerr){
res.send({status:"Fale", Error:newerr });
reject(newerr);
}else{
var newArray = [];
newArray.push( {
_id: ansInfo._id,
UserId: AnsUserData._id,
UserName: AnsUserData.UserName,
UserCategoryId: AnsUserData.UserCategoryId,
UserCategoryName: AnsUserData.UserCategoryName,
UserImage: AnsUserData.UserImage,
UserCompany: AnsUserData.UserCompany,
UserProfession: AnsUserData.UserProfession,
Followers: count,
Date: ansInfo.Date,
PostId: ansInfo.PostId,
PostUserId: ansInfo.PostUserId ,
AnswerText: ansInfo.AnswerText
}
);
AnswersArray.push(newArray[0]);
resolve(newArray[0]);
}
});
}
});
});
}
}).catch(error => {
console.log(error)
})
GetUserData(result);
}
});
};
Finally I will Get The Solution
Thanks To All
Upvotes: 1
Reputation: 39270
Since mongoose should return promises you don't need new Promise. You can use map to map data into promises and then use Promise.all
to wait for them while they all simultaneously execute. Your current code executes queries one by one (only executes the next if current is finished). This is not needed and very slow.
So you can map db.data
to [[first,second],[first,second],...]
. I don't map results of findOne
since that should not return an array and find it strange that something of resultOfFindOne
actually works because findOne should return one document or null.
Both UserModel.UserType.findOne
and UserModel.UserTypeNew.findOne
try to find one record by _id
and both use the same _id
so there is no need to do UserType query then when that comes back do the UserTypeNew query, you can just use info.UserId
for both queries.
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);
If you are using an older version of mongoose (not 5.xxx) you may still need to convert the callback based api to promises, it would look a bit like this:
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
);
Upvotes: 1