Using async functions as conditions - javascript

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 {
}
})

Related

Return value from externally called fs.Readfile() in node

I am trying to get a value returned from a function where I read and write a file using fs.readFile/writeFile in Node.
In my main server.js file, a request comes in and I then want to send an email from another file called sendEmail.js:
const fs = require('fs')
const sendMail = require('./sendEmail')
async function sendAnEmail() {
let resultOfSend = await sendMail.sendEmail()
resultOfSend.then((result)=>{
// return the result
}
}
sendAnEmail();
In sendEmail I first read a file to get the email to send to,
then write to a second file
then, if all is good, I send an email (from a separate function):
async function sendEmail() {
// Check if user exists
fs.readFile('./file.json', (err, data) => {
if(err) {
throw error
}
else {
let users = JSON.parse(data)
let dataToWrite = JSON.stringify(users)
fs.writeFile('./file2.json', dataToWrite, (err) => {
if(err) {
console.error(err)
throw error
}
else {
return generateEmail(users)
.then((info) => {
return info
})
.catch(console.log('err'))
}
})
}
})
}
async function generateEmail(user) {
let msgText = 'hello world'
// Set the mail options
const mailOptions = {
...
}
// Send the mail
let info = await transporter.sendMail(mailOptions)
return info
}
module.exports = {sendEmail}
What I can't get is a value for the resultOfSend variable. Keeps coming back undefined, I think because the promise hasn't yet been fulfilled.
How do I get a value to return from the sendEmail function back to the server.js file where it's called from?
You're using await and async in sendEmail but not returning any Promise (So the sendEmail function doesn't return anything and this is why you get undefined).
Nevertheless, on the response you're trying to call .then() even though you used await.
So you should:
return Promise in the sendEmail function.
decide how you want to handle it, if you use async-await then dont use .then() and just analyze the variable and vice versa.
generateEmail() function should also return Promise.
For example:
async function sendEmail() {
return new Promise((resolve, reject) => {
// Check if user exists
fs.readFile('./file.json', (err, data) => {
if(err) {
reject()
}
else {
let users = JSON.parse(data)
let dataToWrite = JSON.stringify(users)
fs.writeFile('./file2.json', dataToWrite, (err) => {
if(err) {
console.error(err)
reject()
}
else {
generateEmail(users)
.then((info) => {
resolve(info)
})
.catch(
console.log('err')
reject()
)
}
})
}
})
})
}

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.

Use async await function with mongoose query in nodejs

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) {
}

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