Hope you are all doing fine! I am running with some difficulties when I want to deploy this api. I keep on receiving the message:"UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection" My guess is that I am sending a response twice, but I cannot determine where. Does anyone know what could be going on?
`
router.post('/add',async(req,res)=>{
const friend= await User.findOne({username:req.body.friend})
const user=await User.findById(req.body.id)
if(friend&&friend!=req.headers.username){
user.friends.find((x)=>{
switch(friend.username){
case user.username:{
res.status(401).json({
status: "Failed",
message: "We are sorry but you cant add yourself as friend",
data:null
})
}
case x.friend_username:{
res.status(401).json({
status: "Error",
message: `Sorry, your friend has been already added`,
data: []
})
}
default:{
User.findByIdAndUpdate(req.body.id,{
$addToSet:{friends:{
friend_id:friend.id,
friend_username:friend.username
}}
},{upsert:true,safe:true})
.then(result=>{
res.status(200).json({
status: "Success",
message: `Friend has been added correctly! `,
data: result
})
})
.catch((err)=>{
res.status(500).json({
status: "Failed",
message: "Database Error",
data: err
})
})
}
} }
)}
else{
res.status(404).json({
status: "Failed",
message: "We are sorry but the username was not found",
data:null
})
console.log(`There has been an failed attempt of adding a new user. \nUser: ${req.headers.username} `)
}
})
`
CodePudding user response:
Try catch block might help with debugging. And it must be used with async/await to catch unhandled promises. I am assuming that the problem is somewhere within User.findOne() or User.findById(). Ether they are working incorrectly, ether you're passing data in request incorrectly.
router.post('/add', async(req,res)=>{
try {
const friend = await User.findOne({username:req.body.friend})
const user = await User.findById(req.body.id)
if(friend&&friend!=req.headers.username){
user.friends.find((x)=>{
switch(friend.username){
case user.username:{
res.status(401).json({
status: "Failed",
message: "We are sorry but you cant add yourself as friend",
data:null
})
}
case x.friend_username:{
res.status(401).json({
status: "Error",
message: `Sorry, your friend has been already added`,
data: []
})
}
default:{
User.findByIdAndUpdate(req.body.id,{
$addToSet:{friends:{
friend_id:friend.id,
friend_username:friend.username
}}
},{upsert:true,safe:true})
.then(result=>{
res.status(200).json({
status: "Success",
message: `Friend has been added correctly! `,
data: result
})
})
.catch((err)=>{
res.status(500).json({
status: "Failed",
message: "Database Error",
data: err
})
})
}
} }
)}
else{
res.status(404).json({
status: "Failed",
message: "We are sorry but the username was not found",
data:null
})
console.log(`There has been an failed attempt of adding a new user. \nUser: ${req.headers.username} `)
}
} catch(err) {
console.log(err);
}
})
CodePudding user response:
The combination of find() and switch without breaks is probably at the cause, and certainly scrambles the logic.
There are a few other things in the code that can be improved, also. Here's an edit with the changes described in comments...
router.post('/add',async(req,res)=>{
// surround the async calls with try/catch
try {
const friend = await User.findOne({ username:req.body.friend });
const user = await User.findById(req.body.id);
// detect and throw app-level errors. do the express response in the catch
// get the most basic out of the way first. we need a user and a friend for the rest of the route to work
if (!user || !friend) {
throw {
status: 404,
json: {
status: "Failed",
message: "username or friend id not found",
data: null
}
}
}
// user adding themself as a friend doesn't need a loop to check
if (friend.username === user.username) {
throw {
status: 401,
json: {
status: "Failed",
message: "We are sorry but you cant add yourself as friend",
data:null
}
}
}
// the loop that's needed here is hidden in includes()
if (user.friends.includes(friend.username)) {
throw {
status: 401,
json: {
status: "Error",
message: `Sorry, your friend has been already added`,
data:null
}
}
}
// now, all of the errors have been detected and thrown
// do the upsert with another await and send good status
const addToSet = {
$addToSet:{friends:{
friend_id:friend.id,
friend_username:friend.username
}}
};
// note we await here (not then) since that's the style chosen above
const result = await User.findByIdAndUpdate(req.body.id, addToSet,{ upsert:true, safe:true });
res.status(200).json({
status: "Success",
message: `Friend has been added correctly! `,
data: result
});
} catch (error) {
console.log(error);
res.status(error.status).json(error.json);
}
}