why is my error handling not working in express js? - node.js

i just need someone to tell me what is wrong with my code. This is it.
const getSingletask = async (req, res)=>
{
try{
const task = await Task.findOne({_id:req.params.id})
if(!task){
return res.json({msg:`No such task with and id of ${req.params.id}`})
}
res.json({task})
}catch(error){
res.json({msg:error})
}
}
Basically what the code is doing is that whenever the function excutes, it finds one particular item using its ID. The IF statement is the first error handler. It is meant to return that message if the ID cannot be found but it keeps bringing up an error anytime i test it out. I think my code is correct so can someone tell me what i did wrong?

You seem to be using mongoose. Mongoose saves db objects by way of a wrapper called ObjectId, that accepts exactly 24 hex characters. Because the ID you are inputting into it is not 24 hex characters, mongoose fails to cast it (meaning to use the wrapper), and so, throws an error.

Related

Firebase Cloud Functions check is snapshot.exists() error

When I try to run a function
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.checkPostsRef = functions.https.onRequest((request, response) => {
const postId = 'foo'
admin.database().ref('/posts/' + postId).once('value', snapshot => {
if !snapshot.exists() {
console.log("+++++++++ post does not exist +++++++++") // I want this to print
return
}
});
});
I keep getting an error of Parsing error: Unexpected token snapshot:
Once I comment out if snapshot.exists() { .... } everything works fine.
I'm following this link that says there is an .exists() function, so why am I having this issue?
Good to see how you got it working Lance. Your conclusion on the return being the cause is wrong though, so I'll explain the actual cause below.
The problem is in this code:
if !snapshot.exists() ...
In JavaScript you must have parenthesis around the complete condition of an if statement. So the correct syntax is:
if (!snapshot.exists()) ...
In Swift those outer parenthesis are optional, but in JavaScript (and al other C based languages that I know of), they are required.
turns out it was the return; statement that was causing the problem. I had to use an if-else statement instead.
EDIT As #FrankvanPuffelen pointed out in the comments below the question and his answer, this issue wasn't about the return statement, it was about the way i initially had the !snapshot.exists(). Because it wasn't wrapped in parentheses (!snapshot.exists()) which was causing the problem. So it wasn't the return statement, I know very little Javascript and used the wrong syntax.
if (!snapshot.exists()) {
console.log("+++++++++ post does not exist +++++++++");
} else {
console.log("--------- post exists ---------");
}
FYI I'm a native Swift developer and in Swift you don't need to wrap anything in parentheses. In Swift you can do this:
let ref = Database.database().reference().child("post").child("foo")
ref.observeSingleEvent(of: .value, with: { (snapshot) in
if !snapshot.exists() {
print("+++++++++ post does not exist +++++++++")
return
}
})

Unable to find the source of error dialogflow fulfillment

I am trying to create intent in which when the user sends a parameter, then it should be checked in the database that is already there or not. If it already exists user gets a response A and if not it is added to the database, & the user gets response B. I am using Axios to make the API calls. But the code is not working.
I am getting a following errors in the console.
TypeError: Cannot set property 'response' of undefined
at axios.get.then.response (/srv/index.js:33:18)
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:229:7)"
Show matching entries
Hide matching entries
Add field to summary line
I am not a professional, I am doing all this coding by learning from online tutorials and youtube videos Please help.
function idHandler(agent) {
const idcard = agent.parameters.idcard;
const idvalue = ' ';
const idname= ' ';
axios.get('API' + idcard)
.then(response => {
this.response = response.data;
idvalue = this.response[0].IDcard;
idname = this.response[0].Name;
});
if (idcard === idvalue) {
const ans = 'Name of ' + idname + ' is already present in the List';
agent.add(ans);
} else {
const data = [{
idcard: idcard
}];
axios.post('API', data);
}
}
You have a few issues with both how to code for Dialogflow, and how to express some of the syntax correctly. Some of that is because it looks like you're mixing code that expects Promises with code that doesn't.
The axios library is meant to work with Promises - the get and post methods both return Promises. So you can either work with them by using an await method, or by using the .then() method that the returned Promise has. You may want to look up details of both.
Additionally, Dialogflow requires that you either return the Promise, or that your handler be an async function (which will return a Promise for you).
If you're using the .then() approach, however, then everything you do that relies on the call to axios must be done inside the .then() block and you must return that Promise. If you use await, then your function must be declared as an async function. (You can probably mix the two - but don't.)
So that part of your code might look something like:
return axios.get( url )
.then( response => {
// Do EVERYTHING in here
});
And inside the then() code block is where you would extract the values you want, call agent.add() with the message, and possibly make the API call to add data.
While this didn't get flagged as an error, you are trying to assign a value to a const after it is initially set. This is an error. Those should probably be declared using let instead.
Your error looks like it is saying that this is undefined. Which seems... odd. But also not really an issue since you probably don't need to be using this for most of what you're trying to do. If you scope the variables with let, then they should be available for the life of the function.

Getting cast error with ObjectID despite no objectID

I keep getting this error from this code and have no idea why {"Error: CastError: Cast to ObjectId failed for value \"confirmed\" at path \"_id\" for model \"Order\""}
As you can see I am not even using the objectID in this query... I dont know why it is returning this
router.get("/orders/confirmed", async (req, res) => {
try {
const confirmedOrders = await Order.find({ isConfirmed: false })
res.json(confirmedOrders)
} catch (err) {
res.status(400).json("Error: " + err)
}
})
adding my comment as answer because im 99% sure thats it. I have been there....
it looks to me like there is a route above this one one thats more like "/: model/:id". Its finding that route params first. Move that route below this one in your code. That way this specific route will match first then the other one will match if other words\ids are used.
More general note. Always sort route most specific to least specific to try to avoid this. You want /really/specific/ to come before /:something/:else because the handler with match the vars like so if they are in the wrong order... as you see in your current situation.
req.params.something === "really"
req.params.else === "specific"

ExpressJS - function returning undefinded

function checkFamilyStatus() keeps returning undefined for some reason, when it should be returning a boolean value from a mongodb collection.
A bit of context here - I decided to separate the logic part from the router methods like get and post methods, so as to make it look clean and understandable like in functional programming. So I put the logic part in functions and invoke them inside the router methods, but it doesn't work out. Besides, I don't know if this is a good practice or not. Wouldn't it be much easier to read if done like this, instead of say, putting a whole bunch of code in one place?
I've been stuck on this piece of code for a while. I am a bit confused on the working of asynchronous JS as a whole. I did some research, but still don't understand why this wouldn't work. Could someone clarify this up for me?
// post method
router.post("/create", ensureAuthenticated, async(req, res) => {
let userID = req.user.id;
console.log(await checkFamilyStatus(userID)); // but returns undefined
// rest of the code
}
// check family status
checkFamilyStatus = async userID => {
Account.findOne({
_id: userID
}, (err, account) => {
return account.hasFamily; // should return boolean value ?
});
};
Assuming the logic behind account.hasFamily is correct, then you need to await for the return, so it should be return await account.hasFamily;

Mongoose - Post Hook - Change Doc/Model values after load & Before Returning

Solved: I can only guess that delirium got me.
sorry for not figuring it out before posting, but here's the solution for the next persons sake. The try/catch is not necessary, but it did help me get out some errors that were not being printed to console. If there is a better way to document solving my own problem, I'd appreciate the feedback.
Old Question
I have docs stored in my mongo db that I want to modify before being returned to a find() or findOne(). I want to do this without changing the values and a single hook for all find variants. Call it a masking. I'm actually normalizing a numeric value to a scale of 0 to 1. I do not want to modify the value in the doc, just change the values when the doc is returned via find, findOne. E.G. "Change Model values after load in Mongoose"
Solution
schema.post('init', function(doc){
try{
console.log(doc); // prints the doc to console, complete
doc.property = "new property value"; // changes the document value
console.log(doc); // returns the modified document
return doc;
}
catch(error){
console.log(error);
}
}
Old Notes
Other threads note usage of the post init hook. I have tried the methods in the following related topics with no success.
Mongoose - how to tap schema middleware into the 'init' event?
Change Model values after load in Mongoose (this method has changed with 5.x)
schema.post('init', function(doc){
console.log('Tell me i fired'); // works, prints to console
console.log(doc); // works, prints full model to console
doc.valueField = doc.valueField2+doc.valueField3; // fails, no doc returned, throws no errors
});
schema.post('init', function(doc, next){
console.log('Tell me i fired'); // works, prints to console
console.log(doc); // works, prints full model to console
doc.valueField1 = doc.valueField2+doc.valueField3; // fails, no doc returned, throws no errors
next();
});
I've tried adding return(doc);, doc.save() and just about every mutation of the above code I can compile in my shrinking mental capacity. I keep throwing crap at the wall and nothing is sticking. The documentation over at mongoose is poor and the behavior changed with version 5.x with the removal of Asynch call backs (dropped the next() ).
This is a bug submission on mongoose where the dropping of next() is noted.
https://github.com/Automattic/mongoose/issues/6037
release notes from the 5.x release
https://github.com/Automattic/mongoose/blob/master/migrating_to_5.md#init-hook-signatures
~ Edited, because i solved my own problem ~

Resources