why mongoose queries dos not work when put inside promise function - node.js

My code is as shown below:
checkAndCreateUser(customer_id, email_id).then(result => {
console.log("result is " + result);
});
var checkAndCreateUser = function (custom_id, email) {
return new Promise(function (resolve, reject) {
if ((!custom_id) && (custom_id.trim() == '')) {
var creatUser = new user();
// creatUser._id = user_id;
creatUser.ph_no = ph_no;
creatUser.email_id = email;
console.log("fn works");
user.findOne({
'email_id': email
}, function (err, user) {
console.log("db test");
if (!user) {
creatUser.save(function (err, userInfo) {
if (err) {
reject("no id found");
} else {
customer_id = userInfo._id;
resolve(customer_id);
}
});
} else {
customer_id = user._id;
resolve(customer_id);
}
});
}
});
}
Now what happens here is I am not able to successfully run db query. I am able to get console.log("fn works") printed , but it does not print console.log("db test"). So what exactly is going wrong?

You forgot save your user, besides Mongoose already returned promise, you don't need use callbacks:
var checkAndCreateUser = function (custom_id, email) {
return User.create({ ph_no :ph_no,
email_id :email})
.then(result=>{
return User.findOne({'email_id': email})
})
.then(user=>{
return user._id;
})
};
As for mistake in your function:
...
let user = new User({email_id: email, ph_no: phone});
user.save();//you forgot about this
...
You can use save() with callback:
user.save((err, result)=>{...});
Or with promise:
user.save().then(result=>{...}).catch(err=>{...});

Related

cant save data after push to a array in acollection

mongoose function .save() is not working .
async function insertContainerizedData(data, id, farmerId) {
console.log('test id: ', new ObjectId(id));
const user = await Storage.findOne({'containerizedBatches.storage_id': new ObjectId(id)});
console.log('userrrr', user);
if (user == null) {
const containerizedBatched = await Storage.updateOne({'farmer_id': farmerId}, {
$push: {
containerizedBatches: {
storage_id: new ObjectId(data.storage_id),
trace_id: data.trace_id,
batch_id: data.batch_id,
actual_quantity: data.actual_quantity,
remaining_quantity: data.remaining_quantity,
actual_container: data.actual_container,
remaining_container: data.remaining_container,
container_type: data.container_type,
grade: data.grade
}
}
});
const result = await containerizedBatched.save(async (err, result) => {
if (err) {
throw new Error('item is not saved');
} else {
return result;
}
});
console.log('result after push', result);
return result;
its my code and the output is as bellow in postman
What iam trying to do is if the user == null i need to push all the data(req.body) into a array as an object and name of the array is containerizedBatches.
"debugMessage": "containerizedBatched.save is not a function",
You don't need to save after you have already run the update. containerizedBatched is the result of your update operation, not a model to save.

Async function in Node.JS calling SQL Server not working properly

I have a function Im calling to login a user, as follows:
async function loginUser(username, password) {
let msg = {
success: 0,
message: '',
};
sql.connect(process.env.DB_CONNSTRING, function (err) {
if (err) {
res.json(err);
return;
msg.success = '0';
msg.message = 'ERR_04: Could not connect to server.';
return msg;
}
let sqlString = ` SELECT userid
FROM dbo.users
WHERE (email = #username) AND (password = #password)`;
request = new sql.Request();
request.input('username', sql.NVarChar, username);
request.input('password', sql.NVarChar, password);
request.query(sqlString, function (err, results) {
if (err) {
msg.success = '0';
msg.message = 'ERR_011: Could not connect to server.';
return msg;
}
if (results.rowsAffected[0] != 0) {
console.log(results.recordset[0]);
return results.recordset[0];
} else {
msg.success = '0';
msg.message = 'Invalid username and password combination.';
return msg;
}
});
});
}
Please notice a console.log if the query brings back results.
Im calling that function as follows:
await loginUser(username, encryptedPassword)
.then((result) => {
console.log(result);
})
.catch((err) => {
msg.message = 'API Error.';
res.json(msg);
});
Where I also have a console.log()
The problem is that the console.log for the call is coming as undefined, but the one inside the function is throwing the data.
I do not know what I'm missing here, so any help will be appreciated.
Thanks.
If you don't need to call a function, you can try this out.
let sqlString = ` SELECT userid FROM dbo.users WHERE (email ='${username}') AND (password = '${password}')`;
let conn = await sql.connect(process.env.DB_CONNSTRING)
let recordset = await conn.query(sqlString)
res.json(recordset)
In JS if function doesn't have explicit return, it returns undefined.
So, you have a function async function loginUser: async here indicates your function might be ran asynchronous(as promise), but it doesn't return any values;
So, instead of marking you function as async, you need promisify your callbacks and return promise;
It might be something like:
const { promisify } = require('util');
async function loginUser(username, password) {
let msg = {
success: 0,
message: '',
};
await promisify(sql.connect(process.env.DB_CONNSTRING));
let sqlString = `SELECT userid
FROM dbo.users
WHERE (email = #username) AND (password = #password)`;
request = new sql.Request();
request.input('username', sql.NVarChar, username);
request.input('password', sql.NVarChar, password);
return await promisify(request.query(sqlString));
}
Pay special attention on error handling, and where you want(need) call await, and where you don't;

export module return object with added method

I have the following codes :
app.post("/login/auth", (req, res) => {
(async function() {
let NikitaBellucci = (await auth.login(req, db, crypto))[0];
res.send(NikitaBellucci);
})();
});
and
exports.login = (req, db, crypto) => {
pro = new Promise((resolve,reject) => {
let pseudo = req.body.pseudo;
let password = crypto.createHmac('sha256', req.body.password)
.update('jojofags suck')
.digest('hex');
let query = "SELECT * FROM users WHERE users.pseudo = ? AND users.password = ? LIMIT 1";
db.query(query, [pseudo, password], function (err, result) {
if (err) throw err; // GESTION D'ERREURS
result.isAdministrator = function() {
if(this.role <= 90) { return true; } else { return false; }
}
resolve(result);
});
})
return pro.then((val) => {
console.log(val);
return val;
})
}
On console.log(val);, I can see the previously added method to my object. But when returning it to my main file, method "disappear", how to avoid that?
thank you
Your function is attached to the entire result object, but you get the 0 property of it in (await auth.login(req, db, crypto))[0]; which won't have the function. Just remove the [0] and NikitaBellucci.isAdministrator will be the function in question.

Unable to retrive data and push inside loop in node js

I am trying to retrieve attendance list along with user details.
I am using caminte.js(http://www.camintejs.com/) Cross-db ORM for database interaction.
Here is my code sample of model function "attendanceList".
exports.attendanceList = function (req, callback) {
var query = req.query;
var searchfilters = {};
if(!req.user){
callback({ code:400, status:'error', message: 'Invalid Request', data:{}});
}else{
searchfilters["vendor_id"] = parseInt(req.user._id);
}
if(query.location && parseString(query.location) != '') {
searchfilters["location"] = parseString(query.location);
}
if (query.device_details && parseString(query.device_details) != '') {
searchfilters["device_details"] = parseString(query.device_details);
}
if(query.created_on) {
searchfilters["created_on"] = query.created_on;
}
if(query.status) {
searchfilters["status"] = { regex: new RegExp(query.status.toLowerCase(), "i") };
}
var SkipRecord = 0;
var PageSize = 10;
var LimitRecord = PageSize;
var PageIndex = 1;
if(query.pagesize) {
PageSize = parseInt(query.pagesize);
}
if(query.pageindex) {
PageIndex = parseInt(query.pageindex);
}
if (PageIndex > 1) {
SkipRecord = (PageIndex - 1) * PageSize;
}
LimitRecord = PageSize;
var SortRecord = "created_on";
if(query.sortby && query.sorttype) {
var sortingBy = query.sortby;
var sortingType = 'ASC';
if(typeof query.sorttype !== 'undefined') {
sortingType = query.sorttype;
}
SortRecord = sortingBy + ' ' + sortingType;
}
Attendance.find({ where: searchfilters, order: SortRecord, limit: LimitRecord, skip: SkipRecord }, async function (err, result) {
if(err){
callback({ code:400, status:'error', message:'Unable to connect server', errors:err });
} else {
await result.map(function(row, i){
User.findById(parseInt(row.user_id), function(err, data){
if(err){
console.log(err);
} else {
result[i]['userDetails'] = data;
}
});
});
await Attendance.count({ where: searchfilters }, function (err, count) {
callback({ code:200, status:'success', message:'OK', total:count, data:result });
});
}
});
};
I am getting only attendance list without user details. How do I force to push user details into attendance list? Any Help!!
Thank You
This behavior is asynchronous. When you're making request to DB, your code keeps running, while task to get data comes to task queue.
To keep things simple, you need to use promises while handling asynchronous jobs.
Rewrite your code from this:
Attendance.find({ where: searchfilters, order: SortRecord, limit: LimitRecord, skip: SkipRecord }, async function (err, result) {
if(err){
callback({ code:400, status:'error', message:'Unable to connect server', errors:err });
} else {
await result.map(function(row, i){
User.findById(parseInt(row.user_id), function(err, data){
if(err){
console.log(err);
} else {
result[i]['userDetails'] = data;
}
});
});
await Attendance.count({ where: searchfilters }, function (err, count) {
callback({ code:200, status:'success', message:'OK', total:count, data:result });
});
}
});
To this:
const findAttendanceFirst = (searchFilters, SortRecord, LimitRecord, SkipRecord) => {
return new Promise((resolve, reject) => {
Attendance.find({ where: searchFilters, order: SortRecord, limit: LimitRecord, skip: SkipRecord }, (err, result) => {
if(err) return reject(err);
resolve(result);
});
});
}
const findUserByIdForUserDetails = (userId) => {
return new Promise((resolve, reject) => {
User.findById(parseInt(userId), function(err, data){
if(err) return reject(err);
resolve(data);
})
});
}
const getAttendanceCount = (searchFilters) => {
return new Promise((resolve, reject) => {
Attendance.count({ where: searchFilters }, (err, count) => {
if(err) return reject(err);
resolve(count);
});
})
}
So, now we can use this separate functions to make async behavior looks like sync.
try {
const data = await findAttendanceFirst(searchFilters, SortRecord, LimitRecord, SkipRecord);
for(let userData of data){
try {
userData.userDetails = await findUserByIdForUserDetails(userData.user_id);
} catch(e) {
// Some error happened, so no user details.
// you can set here null or nothing to userDetails.
}
}
let count;
try {
count = await getAttendanceCount(searchFilters);
} catch(e){
// Same as before.
}
const callBackData = { code:200, status:'success', message:'OK', total:count, data:result };
// And here you can do whatever you want with callback data. Send to client etc.
} catch(e) {
}
NB: I've not tested this code, it will be easier for yu to play with your actual data and use Promises and async/await
Just remember that each request to db is asynchronous, and you need to make your code wait for this data.

using async await in node js?

I am trying to implement async/await module. In function2 if user is not present i want to stop the execution there . i dont want to execute function 3, if user present , i want to execute function3
const function1() {
//code
return a
}
const function2= (a,email) => model.user.findOne({ email:email}).then((user) => {
if (!user) {
****// want to stop execution here****
} else {
//update details of user
}
return dealer;
});
const function 3 = function(dealer) {
//mail sending
};
exports.mailer = async(email,callback) => {
try {
var a =await function1();
var dealer =await function2(a,email); //stop execution here
var res = await function 3(dealer);
await callback(res);
}catch (err){
callback(err);
}
}
Returning a new Promise in function2 which resolves if a user is found, and rejects if not should achieve what you want I believe.
Something like this:
const function1 = () => {
return a
}
const function2 = (a, email) => {
return new Promise((resolve, reject) => {
model.user.findOne({
email: email
}).then((user) => {
if (!user) {
// want to stop execution here****
reject(new Error('Error Message'))
} else {
// update details of user
resolve(dealer)
}
})
})
}
const function3 = (dealer) => {
//mail sending
}
exports.mailer = async (email, callback) => {
try {
var a = await function1()
var dealer = await function2(a, email) // stop execution here
var res = await function3(dealer)
await callback(res)
} catch (err) {
callback(err)
}
}

Resources