Why mongo query is showing undefined in node js - node.js

I'm trying to check the data with findOne when im trying with the postman getting undefined in console.log , i checked with the same query in roboMongo and its showing the data
this is the result:-
Here is the code:-
exports.signIn = async( req, res ) => {
const {
userEmailPhone,
} = req.body;
await User.findOne ({ email : userEmailPhone}).then((err, user)=> {
console.log("user..", user)
if (user){
res.status(200).send({
message: "sucess"
});
}
})
}
the postman response:-

Since you are already using async - await, I believe there is no need of using the .then() block.
Your code should be updated to use async and await as below:
exports.signIn = async( req, res ) => {
const { email } = req.body;
const user = await User.findOne ({ email : userEmailPhone})
console.log("user..", user)
if (user){
res.status(200).send({
message: "sucess"
});
}
}
If you still want to use the .then() block, I would recommend making the following changes in the code:
exports.signIn = async ( req, res ) => {
const {email} = req.body;
User.findOne ({ email : email}).then((user, err)=> {
console.log("user..", user)
if (user){
res.status(200).send({
message: "sucess"
});
}
})
}
Since the promise callback for MongoDb queries has the following callback format:
.then( (res, err) => {
// do stuff
})
Reference : https://docs.mongodb.com/drivers/node/fundamentals/promises/

You are sending raw json data. First you should use app.use(bodyParser.json());. Only app.use(bodyParser()); is deprecated.
This should fix it assuming you have a json body-parser
exports.signIn = async( req, res ) => {
const {email} = req.body;
User.findOne ({ email : email}).then((err, user)=> {
console.log("user..", user)
if (user){
res.status(200).send({
message: "sucess"
});
}
})
}

Related

can't set status of 400 in express

I have a simple web service and it has a route for register user ,
I want when email exists in DB throw an error with status of 400 or other
I've done it like this
controllers/user.js
const { User } = require('../models/user')
exports.create = async (req, res) => {
try {
const { email } = req.body
const user = await User.findOne({ email })
if (user) {
return res.json({ err: 'email already exists' })
}
await User.userValidation(req.body)
await User.create(req.body)
return res.json({})
} catch (err) {
res.status(400).send({ err })
}
}
BUT , it always give status of 200,
where is the problem ?
Add the status to your response:
if (user) {
return res.status(400).json({ err: 'email already exists' })
}
You can simply send the status 400 when checking if(user)
if(user){
res.status(400).jsom({ err: "Email already exists" });
}
OR
Threat the errors and add a middleware using next (a little bit more complicated then the first one, but more proffessional)
exports.create = async (req, res, next) => {
try {
const { email } = req.body
const user = await User.findOne({ email })
if (user) {
throw new Error("Email already exists");
}
await User.userValidation(req.body)
await User.create(req.body)
return res.json({})
} catch (err) {
next(err, req, res, next);
}
}
In the next middleware you can threat the error and send whatever response you need. (err, req, res objects are sent like references, so you can use them there)

Node JS : How to retrive data from frontend after a res.json(data) in backend?

my backend send a res.staus(200).json({somedata)} to my front, but i can't retrieve the data in the frontend.
My backend :
exports.login = (req, res, next) => {
//===== Check if user exists in DB ======
const { user_email, user_password: clearPassword } = req.body;
let sql = `SELECT user_password, user_id FROM users WHERE user_email=?`;
db.query(sql, [user_email], async (err, results) => {
console.log(results);
console.log(req.body);
if (err) {
return res.status(404).json({ err });
}
// ===== Verify password with hash in DB ======
const { user_password: hashedPassword, user_id } = results[0];
try {
const match = await bcrypt.compare(clearPassword, hashedPassword);
if (match) {
console.log("match ... user_id : ", user_id);
// If match, generate JWT token
res.status(200).json({
test: 'iyu',
user_id: user_id,
token: jwt.sign({ userId: user_id }, "TOOOKEN", {
expiresIn: "24h",
}),
});
} else {
console.log("not match");
}
} catch (err) {
return res.status(400).json({ err: "une erreur" });
}
});
};
The frontend :
const login = async (e) => {
e.preventDefault();
await POST(ENDPOINTS.USER_LOGIN, userLogin);
// await GET(ENDPOINTS.USER_LOGIN)
fetch("http://localhost:4200/api/auth/login")
.then((response) => response.json())
.then((data) => {
console.log(data);
});
};
This login fonction send data to my backend, then the backend checks if an user exist in database with the first POST request. If yes, the backend send in json format some data that i wan't to put in the local storage of the user, so after the POST request, i do another request with GET method to retrieve the json data sent from the back, but i have an 404 error.
How can i get my data sent by the back ?
Seems the problem is with the SQL statement, underneath the if statement you have can you print the error like so:
if(err) {
console.log(err);
}
and tell me the result please

How to return `res` from another function that is called in an express `router`?

I'm trying to do something like this,
// /api/auth
const validateFields = ({ name, email }, res) => {
if (!name.trim()) return res.status(422).json({ error: 'name' })
if (!email.trim()) return res.status(422).json({ error: 'email' })
}
router.post('/', async (req, res) => {
const { name = '', email = '' } = req.body
validateFields({ name, email }, res)
return res.end()
})
If someone passes an invalid name or email, let's say an empty string, the frontend received the expected error, but the backend (ExpressJS) throws an error,
Error: Can't set headers after they are sent
I'm kind of forced to do the following,
const validateFields = ({ name, email }, res) => {
if (!name.trim()) return res.status(422).json({ error: 'name' })
if (!email.trim()) return res.status(422).json({ error: 'email' })
return true
}
router.post('/', async (req, res) => {
const { name = '', email = '' } = req.body
const validFields = validateFields({ name, email }, res)
if (validFields !== true) return
return res.end()
})
Is this my only option here?
That isn't the only way to code it, but you will generally have to check to see if there was an error and, if not, then send your normal response.
I personally don't like functions that sometimes send a response and sometimes don't as that confuses the logic flow. I find it better to either make a function that sends all possible responses or make it a function that just returns status and the caller then sends the response. Or, use the middleware design where if it sends a response, then processing doesn't continue any further (because next() is not called).
In this particular case, you could just return the error status and let the caller send the final response. Then it's always consistent. The response is always sent by the caller and validateFields() just returns a result:
const validateFields = ({ name, email }) => {
if (!name.trim()) return { status: 422, error: 'name' };
if (!email.trim()) return { status: 422, error: 'email' };
return { status: 200, ok: true };
}
router.post('/', async (req, res) => {
const { name = '', email = '' } = req.body;
const result = validateFields({ name, email });
res.status(result.status).json(result);
});
The middleware design could work like this:
const validateFields = (req, res, next) => {
const { name = '', email = '' } = req.body;
if (!name.trim()) return res.status(422).json({ error: 'name' });
if (!email.trim()) return res.status(422).json({ error: 'email' });
next();
}
router.post('/', validateFields, async (req, res) => {
res.send("ok");
});
for validate req.body or req.params use 'Joi', joi is the most powerful schema description language and data validator for JavaScript, check this article

req.params returns undefiened

I'm trying to get back the ID from the params but it keeps sending back undefiened, what would be the problem here and how can i solve it ?
this is the route:
app.delete(`${api_version}/delete-branch/:id`, verifyToken, branches.deleteBranch)
this is the controller:
exports.deleteBranch = (req, result) => {
const {branch_id} = req.params
console.log(branch_id) // => returns undefined
if(branch_id === undefined) {
result.status(404).send({
message: 'This branch does not exist',
statusCode: 404
})
} else {
// console.log(req.params)
Branches.deleteBranch(branch_id, (err, data) => {
if (err) {
result.status(500).send({
message: err.message
})
} else {
result.status(200).send({
message: 'Branch deleted successfully',
statusCode: 200,
data
})
}
})
}
}
You need to destruct req.params like this:
const {id} = req.params
instead of:
const {branch_id} = req.params
Or either defined the route as follow:
app.delete(`${api_version}/delete-branch/:branch_id`, verifyToken, branches.deleteBranch)
and then destruct const {branch_id} = req.params;

Why does my register user post request fail with a 500 error?

I'm building an app with React and Node/Express, and I'm having trouble with my register user function. The data I am passing in is correct, and other endpoints work fine. The register one keeps returning a 500 error and I can't figure out why.
This is my request:
console.log(values)
axios
.post(
'https://foodtrackr-backend.herokuapp.com/api/register',
values
)
.then(res => {
console.log('res.data', res.data);
})
.catch(error => {
console.log('nope');
console.error(error);
});
};
and this is my endpoint:
router.post('/register', async (req, res) => {
let user = req.body;
const newUser = await Users.add(user);
try {
if (newUser) {
res.status(201).json(user);
} else res.status(404);
} catch (error) {
res.status(500).json('noooooo');
}
});
and this is my model:
function findById(id) {
return (
db('users')
.where({ id })
.first()
);
}
async function add(user) {
const [id] = await db('users').insert(user, 'id');
return findById(id);
}
Any help would be appreciated!

Resources