Reputation: 399
I am develop a small app, I have a problem. After I await to run query from Mongodb then I use map method to do some task then I return my response, but the response always return promise and I have not necessary data. Here my code
exports.getListChallenges = async function (req, res) {
var status_code = Consts.STATUS_CODE.ERROR.UNKOWN_ERROR;
try {
var page_number = parseInt(req.params.page_number);
var page_size = parseInt(req.params.page_size);
var challenges = await Challenge.find()
.skip(page_size * (page_number - 1))
.limit(page_size);
status_code = Consts.STATUS_CODE.SUCCESS.DATA_FOUND;
challenges = challenges.map(async function (o) {
var challenger_club = await Club.findById(o.challenger_club_id);
var challege = {
challenge: o,
challenger_club_name: challenger_club.club_name,
challenger_club_avatar: challenger_club.avatar
};
return challege;
});
res.json({
"status": true,
"message": "Challenges found !",
"status_code": status_code,
"challenges": challenges
});
} catch (error) {
status_code = Consts.STATUS_CODE.ERROR.UNKOWN_ERROR;
res.json({
"status": false,
"status_code": status_code,
"error": error
})
}
}
the "challenges" in response always empty , how can I solve it ? thank !
Upvotes: 0
Views: 1580
Reputation: 371138
You're very close - you've mapped each item in the initial challenges
to a Promise
that resolves to the challenge
object you want, now you need to call Promise.all
on that array of Promises
to get the values they resolve to. To keep the code clear, it would be best not to reassign challenges
unless it's necessary - call the new array of Promises something else, like challengePromises
:
exports.getListChallenges = async function(req, res) {
var status_code = Consts.STATUS_CODE.ERROR.UNKOWN_ERROR;
try {
var page_number = parseInt(req.params.page_number);
var page_size = parseInt(req.params.page_size);
var challenges = await Challenge.find()
.skip(page_size * (page_number - 1))
.limit(page_size);
status_code = Consts.STATUS_CODE.SUCCESS.DATA_FOUND;
var challengePromises = challenges.map(async function(o) {
var challenger_club = await Club.findById(o.challenger_club_id);
var challege = {
challenge: o,
challenger_club_name: challenger_club.club_name,
challenger_club_avatar: challenger_club.avatar
};
return challege;
});
var challengeObjs = await Promise.all(challengePromises);
res.json({
"status": true,
"message": "Challenges found !",
"status_code": status_code,
"challenges": challengeObjs
});
} catch (error) {
status_code = Consts.STATUS_CODE.ERROR.UNKOWN_ERROR;
res.json({
"status": false,
"status_code": status_code,
"error": error
})
}
}
Also, just a suggestion, but if you're using async
and await
, you might consider going all the way with ES6+ syntax, such as const
instead of var
, arrow functions when possible, shorthand object properties, among other things - they can make code more concise and readable. For example, I'd refactor your code to:
exports.getListChallenges = async function(req, res) {
try {
const page_number = parseInt(req.params.page_number);
const page_size = parseInt(req.params.page_size);
const challengeData = await Challenge.find()
.skip(page_size * (page_number - 1))
.limit(page_size);
const status_code = Consts.STATUS_CODE.SUCCESS.DATA_FOUND;
const challengePromises = challengeData.map(async (o) => {
const {
club_name: challenger_club_name,
avatar: challenger_club_avatar
} = await Club.findById(o.challenger_club_id);
return {
challenge: o,
challenger_club_name,
challenger_club_avatar
};
});
const challenges = await Promise.all(challengePromises);
res.json({
status: true,
message: "Challenges found !",
status_code,
challenges
});
} catch (error) {
const status_code = Consts.STATUS_CODE.ERROR.UNKOWN_ERROR;
res.json({ status: false, status_code, error })
}
}
Note that the status_code
will always be Consts.STATUS_CODE.ERROR.UNKOWN_ERROR
when there's an error, given the logic on your original code - there's no need to reassign it.
Upvotes: 3