Node js route need to wait for processing of another request - node.js

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.

Related

req.sessionStore.all await not working in node.js with mongoDB

/* đź™… current working */
export const userProfile = async (req, res) => {
const loggedInUserList = [];
const {
params: { id }
} = req;
// await not working..
await req.sessionStore.all((error, sessions) => {
sessions.forEach((session) => {
loggedInUserList.push(session.user._id);
console.log("I want first", loggedInUserList);
console.log(loggedInUserList.includes(id));
});
});
console.log("I want second", loggedInUserList);
const isUserLogin = Boolean(loggedInUserList.includes(String(id)));
console.log("I want third", isUserLogin);
const user = await User.findById(id)
.populate("boards")
.populate("followUsers")
.populate("followingUsers");
return res.status(200).render("user-profile", { user });
};
I want to get sessions from req.sessionStore, after this check user who have req.params.id is loggedIn by if user id in sessions. but await not working..
this is result
I want second []
I want third false
I want first ['6241c87a3e95f193789c9ae0'] <- this is user id
true
(⬇️ I want result like this.)
I want first ['6241c87a3e95f193789c9ae0']
true
I want second ['6241c87a3e95f193789c9ae0']
I want third true
for get like this result, I tried await. but still not working...
Never use promise-based methods and callback based methods together. That means, either use async await/ promise based methods or callback functions.
Since, you are using async functions, using await is most suitable. Your correct code will be:
const sessions = await req.sessionStore.all();
sessions.forEach((session) => {
loggedInUserList.push(session.user._id);
console.log('I want first', loggedInUserList);
console.log(loggedInUserList.includes(id));
});

How to stop API GET request once data is fetched successfully

My question is strictly related to MEAN stack. I want to fetch the total count of documents stored in my MongoDB databse. My express server is working fine but on postman I can see still it is still making request even though i got correct count on console:
Here is my code:
api.js
const uri = 'mongodb://tanzee.......ue&w=majority'
const { MongoClient } = require("mongodb");
const client = new MongoClient(uri);
router.get('/totalmovies', function(req, res) {
run().catch(console.dir);
});
async function run() {
try {
await client.connect();
const database = client.db("mycollection");
const movies = database.collection("movies");
const estimate = await movies.estimatedDocumentCount();
console.log(`Estimated number of documents in the movies collection: ${estimate}`);
} finally {
await client.close();
}
}
I took help from the official doc of mongodb: https://docs.mongodb.com/drivers/node/usage-examples/count/
Output:
(node:15511) DeprecationWarning: current URL string parser is deprecated, and will be removed in a future version. To use the new parser, pass option { useNewUrlParser: true } to MongoClient.connect.
Estimated number of documents in the movies collection: 80
I'm new to this stack. Once the output is fetched, my code should stop the GET call immediately. Please point out my mistakes.
Your code is correct, the request is pending as you are not sending any response thats why the requester is still waiting to receive one. A simple fix is to send data back to the requester.
router.get('/totalmovies', async function(req, res) {
const result = await run();
// check how are you getting result when it is a success/failure
// apply condition same in the below if/else
// it just for reference, it might be correct though
if (result > 0) {
res.status(200).send(result);
} else {
res.status(404).send({'No Data in DB'});
}
});
(node:15511) DeprecationWarning: current URL string parser is
deprecated, and will be removed in a future version. To use the new
parser, pass option { useNewUrlParser: true } to MongoClient.connect.
for this to work:
const client = new MongoClient(uri, { useNewUrlParser: true })
Don't close and rebuild the connection for every request:
async function run() {
try {
await client.connect();
const database = client.db("mycollection");
const movies = database.collection("movies");
const estimate = await movies.estimatedDocumentCount();
console.log(`Estimated number of documents in the movies collection: ${estimate}`);
return estimate;
} catch (e){
console.error('Error in fetching the data from DB')
}
}

function delaying on node.js

Im on a big problem, I need to do an application that gets trello content as soon as i can but i dont know why my for isnt working as it should do. when i the output of this should be the card id and when the function is called it should show the member. I dont know why, but when the 'miembro' function is called, it delays and it is shown after the second id, so its delayed a lot and i need them to show one under the other. I appreciate a quick answer, thank you!
const trelloKB = require("trello-kb");
const fetch = require('node-fetch');
// Replace this by the application key of your Trello account
var appKey = '51501902fff527d305686a29d6d61cfa';
// Replace this by a valid authorization token
var authToken = '9828f5f03073ae52ffdae77bdf49c939df8a315b169cb81aeb42a3d43d0f9e21';
function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
function miembros (id){
fetch('https://api.trello.com/1/cards/'+id+'/members?key=51501902fff527d305686a29d6d61cfa&token=9828f5f03073ae52ffdae77bdf49c939df8a315b169cb81aeb42a3d43d0f9e21&fields=fullName', {
method: 'GET'
})
.then(response => {
setTimeout(function() {
return(response.text());
}, 3000);
})
.then(text => console.log(text))
.catch(err => console.error(err));
}
trelloKB.get(appKey, authToken, '33CP31Sf').then(
function (cards) {
// Print the title of each card
var ms = 3000;
for(i=0; i<2; i++){
var card = cards[0];
var id = card.id;
var titleCard = card.title;
console.log(id);
miembros(id);
}
},
);
I think you should learn about synchronous and asynchronous concept
You need to use async-await and return a promise in your function miembros()
read this async await and promise.
this is my example
const cards =[{id:1,title:'kimiwo'},{id:2,title:'namae wa'},{id:3,title:'udiiiin'}];
yourname(cards);
async function yourname (cards) {
for(let card of cards){
console.log(`id :${card.id},text:${card.title}`);
let result = await(await miembros(card.id)).text();
console.log(result);
}
}
function miembros(id){
return fetch('https://api.trello.com/1/cards/'+id+'/members?key=51501902fff527d305686a29d6d61cfa&token=9828f5f03073ae52ffdae77bdf49c939df8a315b169cb81aeb42a3d43d0f9e21&fields=fullName')
}
you can see the result here
*Edit
fetch returns promise, so you can just return fetch and wrap your function with async-await
It’s delayed because you need to use a sync await or .then
You need to get the first Id first, then do a .then to get the second ID through the function call.
Also, you shouldn’t show you API keys, they’re supposed to be private lol

Synchronously iterate through firestore collection

I have a firebase callable function that does some batch processing on documents in a collection.
The steps are
Copy document to a separate collection, archive it
Run http request to third party service based on data in document
If 2 was successful, delete document
I'm having trouble with forcing the code to run synchronously. I can't figure out the correct await syntax.
async function archiveOrders (myCollection: string) {
//get documents in array for iterating
const currentOrders = [];
console.log('getting current orders');
await db.collection(myCollection).get().then(querySnapshot => {
querySnapshot.forEach(doc => {
currentOrders.push(doc.data());
});
});
console.log(currentOrders);
//copy Orders
currentOrders.forEach (async (doc) => {
if (something about doc data is true ) {
let id = "";
id = doc.id.toString();
await db.collection(myCollection).doc(id).set(doc);
console.log('this was copied: ' + id, doc);
}
});
}
To solve the problem I made a separate function call which returns a promise that I can await for.
I also leveraged the QuerySnapshot which returns an array of all the documents in this QuerySnapshot. See here for usage.
// from inside cloud function
// using firebase node.js admin sdk
const current_orders = await db.collection("currentOrders").get();
for (let index = 0; index < current_orders.docs.length; index++) {
const order = current_orders.docs[index];
await archive(order);
}
async function archive(doc) {
let docData = await doc.data();
if (conditional logic....) {
try {
// await make third party api request
await db.collection("currentOrders").doc(id).delete();
}
catch (err) {
console.log(err)
}
} //end if
} //end archive
Now i'm not familiar with firebase so you will have to tell me if there is something wrong with how i access the data.
You can use await Promise.all() to wait for all promises to resolve before you continue the execution of the function, Promise.all() will fire all requests simultaneously and will not wait for one to finish before firing the next one.
Also although the syntax of async/await looks synchronous, things still happen asynchronously
async function archiveOrders(myCollection: string) {
console.log('getting current orders')
const querySnapshot = await db.collection(myCollection).get()
const currentOrders = querySnapshot.docs.map(doc => doc.data())
console.log(currentOrders)
await Promise.all(currentOrders.map((doc) => {
if (something something) {
return db.collection(myCollection).doc(doc.id.toString()).set(doc)
}
}))
console.log('copied orders')
}

How to push an object into an array in async function

i have been trying to insert an object into an array in async function ,but it
return an empty array as output in nodejs ,mongoose
var data = [];
app.get("/api/post", async (req, res) => {
const post = await UserPost.find();
post.forEach(async element => {
const email = await element.userid;
const user = await Account.find({ email });
const usern = await user[0].username;
var userobject = {
element,
usern
};
//Promise.all(userobject)
data.push(userobject);
});
console.log(data);
res.send({ data });
});
It seems you are struggling with promises. In order to achieve this specific scenario, you can use Promise.all and Array.map.
Here is a code I edited for you:
(*please note that this is just a dummy code for the sake of explanation)
app.get("/api/post", async (req, res) => {
try {
const posts = await dummyPromiseResolver(); // first promise
const promises = posts.map(async element => {
const user = await dummyEmailReturn(element.userid); // second promise
const usern = user[0].username;
return {
usern,
...element
};
});
const fresult = await Promise.all(promises);
res.send(fresult);
} catch (error) {
console.error("error in posts fetch:" + error);
}
});
If I describe this code, posts.map is creating an Array of promises since we need to iterate through every object in the array and needs to add values from separate promises.
Then Promise.all can execute your promise array and return final results array with your desired results.
Note: You can also use for … of as well but when we need to happen things parallelly we use Promise.all. You can find more information from this thread.
here is a link for code sandbox: https://codesandbox.io/embed/serverless-cookies-nu4h0
Please note that I have added dummyPromiseResolver and dummyEmailReturn which would be equal to UserPost.find() and Account.find() functions respectively. In addition to that, I removed a few unnecessary awaits in your code. I added a try catch block to catch any exceptions. You can change that try catch as you please.
hope this will help you. let me know if you need more clarifications.

Resources