Use async await function with mongoose query in nodejs - javascript

I tried to make async and await function in mongoose. but in one case it simply didn't work while in another case it shows syntax error.
here is my code
exports.updateDiscount= async (_id,discount) =>
{
try
{
console.log(_id,discount);
Discount.findOne({_id},(err,user) =>
{
if(user)
{
user.discountRate=parseFloat(discount);
let saveUser= await user.save();
if(saveUser)
{
console.log("Discount saved");
return true
}
}
})
} catch(err)
{
console.log(err);
}
}
I am using the thing function in another module
if( updateDiscount(item.userid,discount) === true)
{
}

Solution ::
exports.updateDiscount= async (_id,discount) =>
{
try
{
console.log(_id,discount);
let user = await Discount.findOne({_id});
if(!!user)
{
user.discountRate=parseFloat(discount);
let saveUser= await user.save();
if(!!saveUser)
{
console.log("Discount saved");
return true
}
}
} catch(err)
{
console.log(err);
}
}

you need to await the function
const answer = await updateDiscount(item.userid,discount);
if(answer) {
}

Related

Using async functions as conditions

Lets say i want to run an if statment where the condition is async function.
const con = require('./con');
if(con.con('email#gmail.com')
console.log('User exists!')
else {
console.log('user does not exist?')
}
This is the function, it uses mongoose findOne which is an async task.
const User = require ('../nodeDB/models/user.js');
const con = function (email) {
User.findOne( { userEmail: email }, function (err, doc) {
if(err) {
console.log(err);
}
if (doc) {
return false;
} else {
return true;
}
});
}
module.exports.con = con;
The problem is that the if statment gets called before the con can get executed which then does'nt set the condition.
You can do it this way :
const con = userEmail => User.findOne({userEmail}).lean().exec();
(async () => {
if (await con('email#gmail.com')) {
console.log('User exists!')
} else {
console.log('user does not exist?')
}
})()
Return User.findOne from your function.
(optional) 2. Add it .lean() (returns simple JSON, faster)
(optional) 3. Add it .exec() so it returns a true Promise and not just a thenable
now you can simply await con() anywhere inside an async function, just as if it was synchronous.
Firstly your con() function doesn't return anything. You will need to return User.findOne(....)
Your if statement needs to respect the fact that the async task has to complete first.
con.con('email#gmail.com')
.then((exists) => {
if (exists)
console.log('User exists!')
else {
console.log('user does not exist?')
}
})
Or with aynsc/await:
async function checkIfUserExists() {
if (await con.con('email#gmail.com')
console.log('User exists!')
else {
console.log('user does not exist?')
}
}
Use await or put your logic in then block.
// must be in async declared function
if (await foo()) {
}
else {
}
// or
foo().then(res=>{
if (res) {
}
else {
}
})

Javascript - .catch async callback

Is it an anti-pattern to use an async method for catching errors?
await something().catch(aysnc (err) => {
console.log(err);
await rollback();
});
I am doing this because I need to make sure that the rollback has been executed before letting the user execute the method again:
const method = async () => {
if(isExecuting.current) return;
isExecuting.current = true;
await something().catch(aysnc (err) => {
console.log(err);
await rollback(); <--- I NEED TO AWAIT THIS TOO
});
isExecuting.current = false;
}
you can do it more clearly using try and catch
const method = async() => {
if (isExecuting.current) return;
isExecuting.current = true;
try {
await something();
} catch (err) {
console.log(err);
await rollback();
}
isExecuting.current = false;
}

How do I convert promises to async await

login() {
return new Promise((resolve, reject) => {
userCollection.findOne({email: this.data.email}).then((myUser)=>{
if (myUser && myUser.password == this.data.password) {
resolve("Congrats! Successfully logged in");
} else{
reject("Login failed");
}
}).catch(()=>{
reject("Please try again later")
})
})
}
This is my model and I can use it to find data from Mongodb. I'm using express js. But, I want to know how I can use async await to do exactly the same thing that the above promise does. I mean, I would like to convert this code to async await way.
Any assistance would be highly appreciated.
This should suffice:
async function login() {
try {
const user = await userCollection.findOne({ email: this.data.email });
if (user && user.password === this.data.password) {
// handle valid user
}
else {
// handle not found user or password mismatch
}
}
catch (error) {
// handle or rethrow error
}
}
Duplicating your case will result in:
async function login() {
try {
const user = await userCollection.findOne({ email: this.data.email });
if (user && user.password === this.data.password) {
return 'Congrats! Successfully logged in';
}
else {
throw new Error('Login failed');
}
}
catch (error) {
throw new Error('Please try again later');
}
}
Then in your caller code you can await(or .then() it, but prefer await) the result of login:
try {
const loginResult = await login();
}
catch(error) {
// handle error
}
Note that in doing so, you will once again need to mark the caller function as async for you to be able to use the await operator.

Confused between promise and async/awaits

I'm a novice in Node JS. I practice promise and I successfully used it. What I understand is with using a promise you can hold the output and send resolve and reject. I used in database operation.
Then someone suggested me to use async/awaits. So here is my code which ran successfully the first time.
shop.js file
const models = require("../models");
const shopModel = models.Shop;
exports.checkShop = function(shopName) {
return new Promise((reslove, reject) => {
shopModel
.findOne({ where: { shop: shopName } })
.then(rs => {
if (rs) {
reslove(rs);
}
})
.catch(err => {
reject(err.toString());
});
});
};
And the file where i called this
const shopController = require("./shop");
exports.getInstall = function(req, res) {
const shop = req.body.shop;
if (!cn(shop)) {
shopController
.checkShop(shop)
.then(
shopCheck =>
function() {
if (shopCheck) {
res.send(`Welcome back ${shopCheck.shop}`);
} else {
//my else stuff
}
}
)
.catch(
e =>
function() {
res.state(500).send(e);
}
);
} else {
return res
.status(400)
.send(
"Missing shop parameter. Please add ?shop=your-development-shop.myshopify.com to your request"
);
}
};
And this is how I tried to replace it with async/awaits. But it does not work.
exports.checkShop = async function(shopName) {
try{
var rs = await shopModel.findOne({ where: { shop: shopName } });
if(rs){
return rs;
}
else{
return false;
}
}
catch(e){
return Promise.reject(new Error(400));
}
};
And the other file
exports.getInstall = function(req, res) {
const shop = req.body.shop;
if (!cn(shop)) {
var shopCheck = shopController.checkShop(shop);
try {
if (shopCheck) {
res.send(`Welcome back ${shopCheck.shop}`);
} else {
// else stuff
}
} catch (e) {
res.state(500).send(e);
}
} else {
return res
.status(400)
.send(
"Missing shop parameter. Please add ?shop=your-development-shop.myshopify.com to your request"
);
}
};
Every function with the async keyword before it will (explicitly or implicitly) return a promise.
So when you call shopController.checkShop you will either have to do something like
shopController.checkShop().then(.... )
or make getInstall an async function as well so that you can use await inside it.
exports.getInstall = async function(req, res) {
// other code here..
const result = await shopController.checkShop(shop);
//..
}
Edit:
If you want to make getInstall async and use await on checkShop you will have to catch the potential rejection using try {} catch like you did in checkShop.

how to handle new Error() in node.js using ES6 Symbol?

I am creating a endpoint in node.js using ES6 Symbol. Example
// ES6 Symbol Method
const taskCreationMethod = {
[Symbol.taskMethod]() {
return {
storeCheckFunc: async function(storeId, employeeId) {
let store = await resourceModel["stores"].findById(storeId).populate(references["stores"]);
if(!store) {
return new Error("Store not found");
}
let employeeCheck = _.find(store.employees, (empObj) => {
return empObj._id == employeeId
})
if(!employeeCheck) {
return new Error("Employee not found");
}
return employeeCheck;
}
};
}
}
//end point
export const taskCreation = async(req, res) => {
const storeCheck = await taskCreationMethod[Symbol.taskMethod]().storeCheckFunc(req.body.store, req.body.assigned_to);
// here How can I handle return with Error Response?
}
You need to throw that error not just return it if you want to use the mechanisms of error handling. The thrown error will become a rejected promise which you can then handle with .catch() directly on the promise or with try/catch if you are using it in an async function. Here's a simplified example:
function populate() {
// always resolves to undefined
return Promise.resolve(undefined)
}
const taskCreationMethod = {
someMethod() {
return {
storeCheckFunc: async function() {
let store = await populate() // always resolves undefined
if (!store) { // so it always fails
throw new Error("Store not found"); // throw error
}
}
};
}
}
// regular promise then().catch()
taskCreationMethod.someMethod().storeCheckFunc()
.then(res => console.log(res))
.catch(err => console.log("Error:", err.message)) // catch
// OR … async function
async function runit() {
try {
let s = await taskCreationMethod.someMethod().storeCheckFunc()
} catch (err) {
console.log("Error:", err.message)
}
}
runit()

Categories