Catch is executed when .then operation is successful - node.js

db('fruit').where('fruit_name', 'apple')
.then(data => {
if (data.length === 0) {
db('fruit').insert({
amount: '2' //just for this post
})
.then(res.sendStatus(200))
.catch(res.sendStatus(500));
}
else {
db('fruit').where('fruit_name', 'apple').update({
amount: '5' //just for this post
})
.then(res.sendStatus(200))
.catch(res.sendStatus(500))
}
})
.catch(error => {
res.sendStatus(500)
})
I don't understand why the catch block is being executed and the server gave me the Can't set header after sending them error. This error occur because I am sending two res.sendStatus. The .then block are working fine and .catch block should not be executed unless the data fails to store in DB.
This is written in knex.js in a Node Express server and for just in case, the query statement is querying the fruit table where fruit_name column's item is equals to apple, insert new amount row if apple doesn't exist else if exist update the amount row.

db('fruit').where('fruit_name', 'apple')
.then(data => {
if (data.length === 0) {
db('fruit').insert({
amount: '2' //just for this post
})
.then(()=>res.sendStatus(200))
.catch(()=>res.sendStatus(500));
}
else {
db('fruit').where('fruit_name', 'apple').update({
amount: '5' //just for this post
})
.then(()=>res.sendStatus(200))
.catch(()=>res.sendStatus(500))
}
})
.catch(error => {
return res.sendStatus(500)
})
Hi calvert. You need to return your responses.This should work fine now.

Related

deleteMany only returns 1 value deleted in change streams

I have a deleteMany request but I am having a hard time in filtering my context of the deleteMany returned value. It only returns 1 value deleted from pusherjs.
Here is my change stream code and pusher code in server side;
if (schedules.operationType === 'delete') {
const scheduleDetails = schedules.documentKey;
pusher.trigger('schedules', 'deleted', {
_id: scheduleDetails._id,
teamOne: scheduleDetails.teamOne,
teamTwo: scheduleDetails.teamTwo,
user: scheduleDetails.user,
isDone: scheduleDetails.isDone,
isStarted: scheduleDetails.isStarted,
date: scheduleDetails.date,
gameEvent: scheduleDetails.gameEvent,
});
}
Here is my pusher code in client side. I am using React by the way. It is stored in my context api;
ScheduleChannel.bind('deleted', ({ deletedSchedule }) => {
console.log(deletedSchedule);
setScheduleList(
scheduleList.filter((schedule) => schedule._id !== deletedSchedule._id)
);
});
here is my code on request;
exports.deleteallmatch = async (req, res) => {
try {
const { sub } = req.user;
const deletedMatches = await Schedule.deleteMany({ user: sub });
return res.status(201).json({
message: 'All of your schedule is successfully deleted!',
deletedMatches,
});
} catch (err) {
return res.status(400).json({
message: 'Something went wrong.',
});
}
};
The delete request is fine but I want to have realtime in my app. Cuz it happened that only one data is being send instead of many. How can I solve this?
The deleteMany() method returns an object that contains three fields:
n – number of matched documents
ok – 1 if the operation was successful
deletedCount – number of deleted documents
What you can do is:
First find all elements that match your query
Store them in some variable
Perform deleting
Return the stored variable
let deleted_items = await Schedule.find({ user: sub });
await Schedule.deleteMany({ user: sub });
return res.status(201).json({
message: 'All of your schedule is successfully deleted!',
deleted_items,
});

Wait until previous query is complete before running the next one

The code below forms part of a websocket that connects to a third party API and receives messages quite frequently from it, currently there are about 3 messages that all appear in very quick succession and I was wondering how I could make sequelize wait until executing one query before the next
this.client.ws.on(WebSocketEvent.ON_MESSAGE, async (message) => {
if (message.type == 'received') {
await db.Order.create({
symbol: message.product_id,
orderId: message.order_id,
price: message.funds,
side: message.side,
orderedAt: message.time,
sold: false
}).catch(err => {
console.log(err);
process.exit();
});
} else if (message.type == 'match') {
await db.Order.update({
volume: message.size
}, {
where: {
orderId: message.taker_order_id
}
}).catch(err => {
console.log(err);
});
} else if (message.type == 'done') {
console.log(message);
await db.Order.update({
completeAt: message.time
}, {
where: {
orderId: message.order_id
}
}).catch(err => {
console.log(err);
});
}
});
Basically what should happen is a message should come through with the type received and that creates a row in the Order table, a split second later a match message should come through and theoretically it should wait for the previous query to run before updating the previously created order, although this is not the case and the model is not updated.
I've thought about simply adding a delay to the code blocks below the match and done message types but would there be any other way to implement what I am looking for?

What return value of sequelize when update?

I am write API in expressjs with Sequence. But I got problem with return value when update!
I follow a tutorial on internet but it got error when num=[1] not num=1 although updating success!
exports.update = (req, res) => {
const { id } = req.params;
Post.update(req.body, {
where: { id }
})
.then((num) => {
if (num === 1) {
res.send({
message: 'Post was updated successfully.'
});
}
else {
res.send({
message: `Cannot update Post with id=${id}. Maybe Post was not found or req.body is empty!`
});
}
})
.catch((err) => {
res.status(500).send({
message: `Error updating Post with id=${id}`
});
});
};
So, what return value after call update method? and how do I solve it? Thanks.
The sequelize document of update is
public static async update(values: object, options: object): Promise<Array<number, number>>
Promise<Array<number, number>>
The promise returns an array with one or two elements. The first element is always the number of affected rows, while the second element is the actual affected rows (only supported in postgres with options.returning true).
So, it will not return only the number. you need to follow the document.
To resolve
.then((nums) => {
const num = nums[0]
.....

How to count URL visit in Nodejs , express?

I am trying to make this basic CRM and here i need to see how many times the link has been visited by the client! is there any way i can do that and store ?
Actually I did this, as Ravi Teja said comment.
Added userClicks in the database model in case of mongoose.
(This is nested into another object)
analytics: {
userClicks: {
type: Number,
default : 0
}
}
When any request hits to that URL, I just update that count by one.
app.get('URL', (req, res) => {
//First find document in database
Url.findOne({
$text: {
$search: request.params.shortUrl
}
}).then(url => {
if (url === null) {
return response.status(404).json({
message: "Link in not valid"
});
} else {
//If successfully found, get already stored value and updated with +1, and then update that document.
const _id = url._id
let counterClicks = url.analytics.userClicks;
//Update existing values
counterClicks++;
Url.findByIdAndUpdate({
_id
}, {
$set: {
'analytics.userClicks': counterClicks
}
}).exec().then(url => {
console.log(url);
return response.redirect(302, url.originalUrl);
}).catch(error => {
console.log(error);
});
}
}).catch(error => {
console.log(error);
});
});
You can do this by newer async-await syntax.
From the above's code snippet, we will get idea, How to implement it.

NodeJS mongoose query and promise

So, I am new to nodejs. I don't just want to solve this problem, but I also want to learn this concept.
1 Prize has Many Winners. Both are separate tables. I first get list of prizes related to a certain id. I loop through those prizes using Promises.all() and then, for each prize, I query for winners.
Here is my code:
router.post("/getResult", function (req, res) {
const lottery_id = req.body.lottery_id;
const data = [];
//Find list of prices for given lottery_id. Note the sorting applied here
Prize.find({"lotid": lottery_id}).sort({name: 1})
.then(async function (prizes) {
try {
await Promise.all(prizes.map(async (prize) => {
//Sorting here works fine as confirmed by this log.
console.log(prize.name);
await Winner.find({"id": prize._id})
.then(function (winners) {
data.push({
prize: prize,
winners: winners
});
})
}));
//Sorting here is completely messed up.
// Something wrong with second query "Winner.find() and pushing data
res.send({success: 1, data: data});
} catch (err) {
console.log("Error " + err);
res.send({success: 0, data: err});
}
}).catch(function (err) {
res.send({success: 0, error: err});
})
});
The final result that I get doesn't follow the sorting applied to prize. May be, the query Winner.find() for 2nd prize finishes before 1st prize and hence, it is pushed in data before 1st prize.
You are seeing an unexpected sorted result because there is no coordination with how you are pushing values into the data array. prizes.map() does iterate over the prizes array sequentially, however, there is no guarantee that each mapped promise, or more specifically each Winner.find(), will become fulfilled in the same order chronologically.
One way you could fix this is to use the return value of Promise.all(). Here is an example:
router.post("/getResult", async function (req, res) {
const lottery_id = req.body.lottery_id;
try {
const prizes = await Prize.find({ "lotid": lottery_id }).sort({ name: 1 });
const prizeWinners = await Promise.all(prizes.map(async function(prize) {
const winners = await Winner.find({ "id": prize._id });
return {
prize,
winners
};
}));
res.send({ success: 1, data: prizeWinners });
} catch (err) {
res.send({ success: 0, error: err });
}
});

Resources