Reputation: 11
I'm using Nodejs with MongoDB(mongoose along with express).
Since I don't trust the user data, I need to verify it from the database.
input data:
{
"id": "someid",
"nottrusteddata": [ {"id": "1"}, {"id" :"2"}]
}
In my function, I'm verifying the data:
router.post("/validate", (req, res,next) =>{
let validated_data = validate_data(req);
console.log(JSON.stringify(validated_data));
const mydata = new Mydata({
id: req.body.id,
lst : validated_data
});
console.log("mydata: " + JSON.stringify(mydata));
/* Some Usefull stuff is here */
res.status(200).json();
}
function validate_data(req){
let validated_data = []
for(let i = 0; i < req.body.nottrusteddata.length; i++)
{
Databaseobject.findOne({'id': req.body.nottrusteddata[i].id})
.exec()
.then(dbobject =>{
if(dbobject) // not undefined, it exists in the database
{
// Some logic with the object returned from the database
let tmp_object = {};
tmpobject.id = dbobject.id;
// Append it to the list, so that the upper function can use it
validated_data.push(tmp_object);
}
})
}
return validated_data;
}
The desired output should contain the correct information coming from the database, however, due to the async nature of the nodejs, validated_data
returns null.
I have also tried using Promise
. I couldn't succeed it.
const validate_data = function(req){
return new Promise(function(resolve,reject){
let validated_data = []
for(let i = 0; i < req.body.nottrusteddata.length; i++)
{
Databaseobject.findOne({'id': req.body.nottrusteddata[i].id})
.exec()
.then(dbobject =>{
if(dbobject) // not undefined, it exists in the database
{
let tmp_object = {};
tmpobject.id = dbobject.id;
validated_data.push(tmp_object);
}
})
}
resolve(validated_data);
}
}
What am I doing wrong? How can I wait for the database query to finish, then execute the main part? If there is only one validation, I could've used .then()
. However, the list might have contained many elements and I need to wait for all of them to be verified.
Upvotes: 1
Views: 393
Reputation: 12071
Your Databaseobject.findOne()
calls are asynchronous so your promise will resolve before any of them complete.
You can make use of Promise.all
to wait until all of your promises resolve.
Hopefully, this will work for you:
router.post("/validate", (req, res) => {
validate_data(req.body.nottrusteddata)
.then(validated_data => {
const mydata = new Mydata({
id: req.body.id,
lst: validated_data
})
// Some useful stuff is here
res.status(200).json()
})
.catch(err => {
// Handle error
})
}
function validate_data(nottrusteddata) {
// Create array of pending promises
const promises = nottrusteddata
.map(item => {
return Databaseobject
.findOne({ 'id': item.id })
.exec()
})
// Wait for all promises to resolve
return Promise.all(promises)
.then(docs => {
return docs
.filter(dbobject => dbobject) // Filter out undefined
.map(dbobject => {
return { id: dbobject.id }
})
})
}
If you want, you could also use async-await here:
router.post("/validate", async (req, res) => {
try {
const validated_data = await validate_data(req.body.nottrusteddata)
const mydata = new Mydata({
id: req.body.id,
lst: validated_data
})
// Some useful stuff is here
res.status(200).json()
}
catch(err) {
// Handle error
}
})
Upvotes: 1