await/async: compiler/syntax issue with conditionnals - node.js

I am using async/await in a web app to query a DB and use results for other queries.
I have this function:
exports.getByUserAndPurposeForService = async (req,res,next) =>{
var serviceID = await Service.getIdByName(req.params.serviceName)
var user_id = await User.getIdByName(req.params.userID)
if(condition){...}
Await/async works great there but whet it gets to this point:
else {
var userName= **await** ID.getUserID(serviceID, req.params.userID)
user_id = **await** User.getIdByName(userName)
}
else{
res.send('Not Allowed')
}
}
})
those two 'await' create an error in the IDE :
'Parsing error : unexpected token ID'
I don't know why, I can use await on functions outside the conditional but not inside.

Thanks a lot for all the help, I found what the problem was :
I was awaiting these promises inside a .exec() function
Like this :
Model.findOne({..}).exec(function(err, result){
var user = await ...
})
You can't apparently mix chaining with async/await
Thanks for the help !
So I fixed it by using await on Model.findOne({..}).exec() and storing result in variable I could use after

Related

mongoose Query was already executed

I was trying to learn a MERN stack beginner tutorials and i encountered this problem the query was already executed I'm getting this error whenever .findOne() is executed:
MongooseError: Query was already executed: elders.findOne({ _id: new ObjectId("636caae0e3c24f1df7b4e6b7...
router.put("/updateElders", async (req,res)=>{
const newAge = req.body.newAge
const id = req.body.id
try{
await EldersModel.findById(id, (error, eldertoUpdate) =>{
eldertoUpdate.age = Number (newAge);
eldertoUpdate.save();
})
}catch(err){console.log(err);}
You should decide on whether to use callbacks or promises. You chose to use await (used for awaiting promises) and callbacks (your second parameter passed to findById. You should decide on which one to use, e.g.:
router.put("/updateElders", async (req,res)=>{
const newAge = req.body.newAge
const id = req.body.id
try{
const eldertoUpdate = await EldersModel.findById(id);
eldertoUpdate.age = Number(newAge);
await eldertoUpdate.save();
}catch(err){
console.log(err);
}
this code uses promises returned from findById and save calls and awaits those.

Implementing Transaction in node js using mongoose

I am Trying to implement transaction in my project, since I would like to update more than one collection on the same api
I am sharing the sample code, I tried to understand the concept
sample code
const mongoose = require("mongoose");
const session = await mongoose.startSession();
session.startTransaction();
const opts = { session };
try {
const sample = await sample_table.findOneAndUpdate({
user_name : "nishanth"
},{status: "Inactive"},
{opts});
const transaction = await transaction_table.findOneAndUpdate({
bank_name : SBI
},{status: "Inactive"}, { opts });
await session.commitTransaction();
session.endSession();
return res.send({message: "success", sample_data: sample, transaction_data:
transaction});
}catch(err)
{
await session.abortTransaction();
session.endSession();
return res.send({err: err.message});
}
In the above code, I am trying to update two collections status to Inactive with a filter.
I had give an undefined variable for the transaction_table so the second update query will fail before commit and go to catch block and perform abortTransaction
When I use the above code, It updates the sample_table collection in db. could someone explain me where I am going wrong and share me a sample project for the above example
I am using "mongoose": "^5.13.14", version

How to query MongoDB using aysnc/await?

So I'm following a course on Udemy to learn web development using Node/Express/MongoDB and using mongoose to interact with the database.
I have reached a lecture where the instructor started explaining on how to query the database so here created a mongoose model and named it Tour and in a controller file he wrote this to query the data that we already imported like this:
exports.getAllTours = async (req, res) => {
try {
const queryObj = { ...req.query };
const exludedFields = ["sort", "limit", "page", "fields"];
exludedFields.forEach(el => delete queryObj[el]);
const query = Tour.find(queryObj);
const tours = await query
res.status(200).json({
status: 'success',
data: {
tours: tours
}
})
} catch (err) {
res.status(404).json({
status: 'fail',
message: err.message
});
}
}
As you can see from the code above we used the handler function getAllTours to get all the tours which by the way it handles this route app.get('/api/v1/tours/').
At the beginning of the lecture the code for the query was like this: const query = await Tour.find(queryObj); and then he removed the await keyword to look like the code above were he included the await keyword for the tours object later.
The instructor explained this by saying that if we used the await on the query like this const query = await Tour.find(queryObj); then the code will execute immediately and then we would not be able to chain other methods on the query like .where() or .equals().
I need someone to explain these questions for me:
why would the code execute immediately if we used await?
the Tour.find() does need time to query the database, so I think we should add await, shouldn't we?
The Tour.find() returns a promise (is an async call), adding the await in front of it will wait until the promise is resolved and return it results.
If you want to do a where() after you do the find you can do it after the query is executed since you will have the results in that object in your case the tours object.
Honestly I prefer doing const tours = await Tour.find() you save a varaible that is kinda of innecesary, just is necesary if you want to catch an error of the promise or something like that.
In your case you using a try catch so the error will go to the catch block if something happens with the query (connection issues or other problems)

Node js route need to wait for processing of another request

We processing the order requests, on the time of multiple HTTP requests hitting the same route function means the function not working properly
Actually, we write the async await operation for all DB related queries
our coding example is
buyCtrl.orderPlace = async function (req, res, next) {
var response = await table1.find({exchange:ref_m}).sort({_id:-1}).limit(1);
if(response.length > 0)
{
var incRes = await table2.findOneAndUpdate({_id:1},{a:b}, {new: true});
var OrdersIns = new Orders();
OrdersIns.userid = userid;
OrdersIns.from = 'a';
OrdersIns.to = 'b';
await OrdersIns.save();
await compare(positiondetails[0]);
res.status(200).json({status:true,message:'Order placed successfully'});
}
}
const compare = async (curOrder) => {
var result = await Orders.find({userid:mongoose.Types.ObjectId(userid),type:opp}).sort({posTimestamp:1});
if(result.length>0)
{
for(var pi=0;pi<result.length;pi++)
{
if(parseFloat(curOrder.qty)==parseFloat(result[i].qty))
{
var updatedata = {a:b}
await Orders.findOneAndUpdate({_id:mongoose.Types.ObjectId(curOrder._id)}, updatedata, {new: true});
await Orders.remove({_id:mongoose.Types.ObjectId(result[i]._id)});
}
else
{
var updatedata = {a:b}
await Orders.findOneAndUpdate({_id:mongoose.Types.ObjectId(result[i]._id))}, updatedata, {new: true});
await Orders.remove({_id:mongoose.Types.ObjectId(curOrder._id)});
}
}
}
}
This is the flow we have I cannot paste my full code so make some example code
Please check and share your ideas
when we make an automation test with more concurrent requests the compare and update is not working properly
Thanks in advance
For atomic operations such as increment and decrement, this can be done using MongoDB's provided API. Another solution is to work with versioning, which MongoDB provides out of the box. The concurrent connection might update the object which changed before the update could take place.

How to use multi query with nodejs express mongodb

How to use multi query like find , update , insert , delete in one service on mongodb
I can query this below
router.get('/userlist', function(req, res) {
  User.find({},function (err, docs) {
    res.json(docs);
  });
});
but i want to query like this is an error
router.get('/userlist', function(req, res) {
  var data = array();
  User.find({},function (err, docs) {
     data['data1'] = docs
  })
  Content.find({},function (err, docs) {
    data['data2']  = docs
  })
  res.json(docs)
});
Can anyone help me or It is possible to use query like this?
Thank you
You can use async await to run multiple mongo queries inside a function like below:
router.get('/userlist', async function(req, res) {
var data = array();
try{
//first query
let user_data = await User.find({}).exec();
data['data1'] = user_data;
//second query
let content_data = await Content.find({}).exec();
data['data2'] = content_data;
return res.status(200).json(data)
}
catch(err){
return res.status(400).json({err})
}
});
My question is what is stopping you? Yes, you can do this. I did those kinds of works.
There remain two points.
If you need to perform multiple queries, based on the response of the previous query, you can use async/await or promises. If you don't wanna try those, there is still a way. You can check the response of the previous query, make conditions, and if right, execute the seconde one. And thus you can make a chain of queries.
And if you don't need to rely on the responses, do whatever you want. There is nothing wrong...
Happy Coding!
You have to wait for your database call response. So, You can use promise for this. MDN: Promise Make promise of database call and resolve that after you got data from database. Promise.all will wait until your both the promises resolved. MDN: Promise.all()
router.get('/userlist', function(req, res) {
var data = [];
let promise1 = new Promise((resolve, reject) => {
User.find({},function (err, docs) {
data['data1'] = docs;
resolve();
})
});
let promise2 = new Promise((resolve, reject) => {
Content.find({},function (err, docs) {
data['data2'] = docs
})
});
Promise.all([promise1, promise2]).then(result => res.json(docs))
});

Resources