I'm trying to make an API call but the customizeObj
is empty in last then.
userRouter.get("/getusers", (req, apiRes) => {
let users;
var customizeObj = [];
User.find()
.then((res) => {
users = res;
})
.then(() => {
users.forEach(async (user) => {
let event = null;
event = await Event.findById(user.eventID);
let year = event.date.getFullYear();
let month =
event.date.getMonth() 1 < 10
? "0" event.date.getMonth() 1
: event.date.getMonth() 1;
let day =
event.date.getDate() < 10
? "0" event.date.getDate()
: event.date.getDate();
customizeObj.push({
firstName: user.firstName,
lastName: user.lastName,
phoneNumber: user.phoneNumber,
zipCode: user.zipCode,
type: event.type,
location: event.location,
date: new Date(`${year}-${month}-${day}`),
});
console.log(customizeObj); // Not empty
});
console.log(customizeObj); // Empty
})
.then(() => {
console.log(customizeObj); // Empty
apiRes.send(customizeObj) // Sends emprty array
})
.catch((err) => console.log(err));
});
can please anyone help me with that? I don't know why it's empty
CodePudding user response:
Based on express and mongoose - this should work as per the above details provided.
userRouter.get("/getusers", (req, res) => {
try{
let customizeObj = [];
//get users and lean
const users = await User.find().lean();
if(!users.length){
//should return empty if users don't exist.
return res.send(customizeObj);
}
//loop over users.
for(let i = 0 ; i < users.length ; i ){
//get event of user by users[i].eventID.
let event = await Event.findById(users[i].eventID).lean();
//if event exists you create the customized object, if doesn't exist again no element will be pushed to customizeObj array.
if(event){
let year = event.date.getFullYear();
let month =
event.date.getMonth() 1 < 10
? "0" event.date.getMonth() 1
: event.date.getMonth() 1;
let day =
event.date.getDate() < 10
? "0" event.date.getDate()
: event.date.getDate();
customizeObj.push({
firstName: users[i].firstName,
lastName: users[i].lastName,
phoneNumber: users[i].phoneNumber,
zipCode: users[i].zipCode,
type: event.type,
location: event.location,
date: new Date(`${year}-${month}-${day}`),
});
}
}
res.send(customizeObj);
} catch(error){
console.log('error in api',error);
res.status(500).send({message: 'unknown error', error});
}
});
Also, you should be creating a ref to events model and use populate('event') to get events in a single query instead of querying in a loop.
CodePudding user response:
The reason for customizeObj to be empty is probably the fact that it hasn't been filled yet. The second .then function where you iterate over users does not return a promise so the next then is executed immediately, it does not wait for the forEach loop to finish.
I have simplyfied your code to only use async await instead of mixing it with Promises(.then)
I believe it's much easier to read and the code should be self explanatory.
userRouter.get("/getusers", async (req, res) => {
let users;
let customizeObj = [];
try {
// use exec for a better stack trace
let users = User.find({}, 'eventID').exec();
// get all events in a single query
let events = await Event.find({ _id: { $in: users.map(u => u.eventID) }}).exec();
users.forEach((user) => {
let event = events.find(ev => ev._id === user.eventID);
let year = event.date.getFullYear();
let month = event.date.getMonth() 1 < 10 ? "0" event.date.getMonth() 1 : event.date.getMonth() 1;
let day = event.date.getDate() < 10 ? "0" event.date.getDate() : event.date.getDate();
customizeObj.push({
firstName: user.firstName,
lastName: user.lastName,
phoneNumber: user.phoneNumber,
zipCode: user.zipCode,
type: event.type,
location: event.location,
date: new Date(`${year}-${month}-${day}`),
});
});
res.json(customizeObj);
} catch(e){
res.json([]);
}
});