I have a following Post route
router.post("/message", async (req, res) => {
const newMessage = new Message({
From: req.body.sendersPhoneNumber,
To: 9188123560,
OTP: req.body.randomNumber,
Message: req.body.TextToSend
})
newMessage.save().then((response) => {
const from = "NEXMO"
const to = response.To
const text = response.Message
nexmo.message.sendSms(from, to, text, {type: 'unicode'}, (error, responseData) => {
if (error) {
console.log(error)
throw new Error (error)
} else {
console.dir(responseData)
res.send(responseData)
}
})
})
})
In this, I want to throw an error If there is an error for which i did something like this
if (error) {
console.log(error)
throw new Error (error)
}
But that doesn't seem to be working, can some help me by sharing, how can we throw an error in nodeJs
This is my request from frontend
axios.post(test_url_base + "/contact/message", this.state).then(response => {
Solution 01:
Line 1: Need a third parameter, next to pass the error to the next handler.
Line 16: pass the error to the next error handler, return next(error);
NB: In your root file like index.js or server.js or whatever you are using, You need an error handler, like,
app.use((err, req, res, next) => {
console.log('Found a error');
});
Your final code will be,
router.post("/message", async (req, res, next) => {
const newMessage = new Message({
From: req.body.sendersPhoneNumber,
To: 9188123560,
OTP: req.body.randomNumber,
Message: req.body.TextToSend
})
newMessage.save().then((response) => {
const from = "NEXMO"
const to = response.To
const text = response.Message
nexmo.message.sendSms(from, to, text, {type: 'unicode'}, (error, responseData) => {
if (error) {
console.log(error)
return next(error);
} else {
console.dir(responseData)
res.send(responseData)
}
})
})
})
Solution 2:
If you encounter an error, pass the error to the client side,
Use res.status(400).send(error);
In this case, your code should be,
router.post("/message", async (req, res, next) => {
const newMessage = new Message({
From: req.body.sendersPhoneNumber,
To: 9188123560,
OTP: req.body.randomNumber,
Message: req.body.TextToSend
})
newMessage.save().then((response) => {
const from = "NEXMO"
const to = response.To
const text = response.Message
nexmo.message.sendSms(from, to, text, {type: 'unicode'}, (error, responseData) => {
if (error) {
console.log(error)
return res.send(error);
} else {
console.dir(responseData)
res.send(responseData)
}
})
})
})
as you have done that is also correct way but i don't get why it is not working.
you can also try this one
if (error) {
return next(error)
}
or you can also do this
res.render('error', { error: err })
Put try catch block , so that any error thrown from try block gets caught in catch block.
router.post("/message", async (req, res) => {
try {
const newMessage = new Message({
From: req.body.sendersPhoneNumber,
To: 9188123560,
OTP: req.body.randomNumber,
Message: req.body.TextToSend
})
newMessage.save().then((response) => {
const from = "NEXMO"
const to = response.To
const text = response.Message
nexmo.message.sendSms(from, to, text, { type: 'unicode' }, (error, responseData) => {
if (error) {
console.log(error)
throw new Error(error)
} else {
console.dir(responseData)
res.send(responseData)
}
})
});
}
catch (e) {
res.send({ status: 400, error: e });
}
})
Related
I have this problem in this part of my code
the curse that I study with there is no problem with the teacher I also search a lot
on this code is the controller of the API that I try to build
exports.create = (req, res, next) => {
upload(req, res, function (err) {
if (err) {
next(err)
}
else {
const path = req.file != undefined ? req.file.path.replace(/\\/g, '/') : "";
var model = {
categoryName: req.body.categoryName,
categoryDescription: req.body.categoryDescription,
categoryImage: path != "" ? '/' + path : ''
}
categoriesService.createCatergry(model, (error, results) => {
if (error) {
return next(error)
}
else {
return res.status(200).send({
message: 'Success',
data: results
})
}
})
}
})
}
that the code in service file
async function createCategory(parmas, callback) {
if (!parmas.categoryName) {
return callback({
massage: 'Category name is required'
},
""
);
}
const model = new category(parmas);
model.save().then((response) => {
return callback(null, response);
}).catch((error) => {
return callback(error);
})
}
when I click on it say remove unsend function
Please check if it's not misspelled createCatergry
I am finding it hard to convert this user controllers code to async await. Can someone please help and guide me how can i do it too. So that i can also change any callbacks into async await.
Also if someone can provide a good source so that i can read about async await and how to apply them properly.
const User = require("../models/user")
exports.getUserById = (req, res, next, id) => {
User.findById(id).exec((error, user) => {
if (error || !user) {
return res.status(400).json({
error: "No user was found in DB"
})
}
req.profile = user
next()
})
}
exports.getUser = (req, res) => {
req.profile.salt = undefined;
req.profile.encrypted_password = undefined;
return res.json(req.profile)
}
exports.getAllUsers = (req, res) => {
User.find().exec((error, users) => {
if (error || !users) {
return res.status(400).json({
error: "No users was found in DB"
})
}
return res.json(users)
})
}
exports.updateUser = (req, res) => {
User.findByIdAndUpdate(
{ _id: req.profile._id },
{ $set: req.body },
{ new: true, useFindAndModify: false },
(error, user) => {
if (error) {
return res.status(400).json({
error: "You are not authorized to update this info"
})
}
user.salt = undefined;
user.encrypted_password = undefined;
res.json(user)
}
)
}
It should look something like this:
const User = require("../models/user");
exports.getUserById = async (req, res, next, id) => {
let user = await User.findById(id);
try {
if (!user) {
return res.status(404).json({
error: "No user was found in DB"
});
}
req.profile = user;
next();
} catch (err) {
return res.status(500).json({
error: "Something went wrong"
});
}
};
exports.getUser = (req, res) => {
req.profile.salt = undefined;
req.profile.encrypted_password = undefined;
return res.json(req.profile);
};
exports.getAllUsers = async (req, res) => {
let users = await User.find();
try {
if (users.length < 1) {
return res.status(404).json({
error: "No users was found in DB"
});
}
return res.json(users);
} catch (err) {
return res.status(500).json({
error: "Something went wrong"
});
}
};
exports.updateUser = async (req, res) => {
try {
let user = await User.findByIdAndUpdate(
{ _id: req.profile._id },
{ $set: req.body },
{ new: true, useFindAndModify: false }
);
user.salt = undefined;
user.encrypted_password = undefined;
return res.json(user);
} catch (err) {
return res.status(400).json({
error: "You are not authorized to update this info"
});
}
};
You should send back 404 errors if you cant find any user in the database. 400 means bad request.
You can achieve what you are asking by wrapping the function with Promise. In your example, you should use the solution given by Ifaruki, because mongoose already supports promises.
function waitSeconds(seconds) {
return new Promise(res => {
setTimeout(() => {
res();
}, seconds * 1000)
})
}
async function foo() {
console.log("Hello");
await waitSeconds(5);
console.log("World");
}
Here you can learn more about async in javascript
I want to handle the error when the user intentionally entered the wrong objectId, but when I compressed the error in a function check objectID, I got this error: UnhandledPromiseRejectionWarning: Error: INVALID_ID
function check obejctID :
function checkObjectId(...ids) {
ids.forEach(id => {
const objectId = mongoose.Types.ObjectId.isValid(id);
if (!objectId) throw new MyError('INVALID_ID',404);
});
}
service :
static async updateAuthor(_id, content) {
checkObjectId(_id);
const author = await Author.findByIdAndUpdate(_id, content, { new: true });
if (!author) throw new MyError('CAN_NOT_FIND_AUTHOR', 404);
return author;
}
router :
routerAuthor.put('/:_id',async (req, res) => {
AuthorService.updateAuthor(req.params._id,req.body)
.then(author => res.send({success : true, author}))
.catch(res.onError);
});
app.use((req, res, next) => {
res.onError = function(error) {
const body = { success: false, message: error.message };
if (!error.statusCode) console.log(error);
res.status(error.statusCode || 500).send(body);
};
next();
});
Try to use try catch:
static async updateAuthor(_id, content) {
try {
checkObjectId(_id);
const author = await Author.findByIdAndUpdate(_id, content, { new: true });
if (!author) throw new MyError('CAN_NOT_FIND_AUTHOR', 404);
return author;
} catch (e) {
throw new Error(e);
}
}
I am building a login/Register portion of my app. Right now I'm using express-validator to check if an email exists in my collection.
This is my route:
var router = require('express').Router()
var UserModel = require('../models/UserModel')
var { body } = require('express-validator');
router
.route('/registration')
.get(function(req, res) {
console.log(0)
UserModel.find({}, (err, users) => {
console.log(1);
if (err) return res.status(500).send(err)
console.log(2);
return res.json(users);
})
})
.post(body('username_email').custom(value => {
console.log("value ", value);
console.log(3)
UserModel.findOne({ 'username_email': value }, (err) => {
console.log(4);
if (err) return res.status(409).send(err);
})
}), async(req, res, next) => {
console.log(5)
try {
let newUser = new UserModel(req.body);
let savedUser = await newUser.save();
console.log(6);
if (savedUser) return res.redirect('/users/registration?success=true');
return next(new Error('Failed to save user for unknown reasons'))
} catch (err) {
return next(err)
}
})
module.exports = router
In my component on the front end I have a function in my fetch which will catch the error if there is one.
handleErrors(response) {
if (!response.ok) {
console.log('This email exists!')
throw Error(response.statusText);
}
return response;
}
handleSubmit(event) {
event.preventDefault()
var { username, password } = this.state
var mailFormat = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
var error = false
if (!username.match(mailFormat)) {
this.setState({ usernameError: true })
error = true
} else {
this.setState({ usernameError: false })
}
if (password.length <= 8) {
this.setState({ passwordError: true })
error = true
} else {
this.setState({ passwordError: false })
}
console.log(`error ${error}`)
if (error == false) {
this.setState({ formError: false, formSuccess: true })
}
window.fetch('http://localhost:8016/users/registration', {
method: 'POST',
headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' },
body: JSON.stringify({ username_email: username, password: password })
})
.then(this.handleErrors)
.then(function (response) {
console.log(`response ${response}`)
return response.json()
}).then(function (data) {
console.log('User created:', data)
}).catch(function (error) {
console.log(error);
});
}
The console.log in the fetch, handleErrors is being registered in the console, but why isn't the error status a 409 like I indicated.
Closer excerpt of post route!
.post(body('username_email').custom(value => {
console.log("value ", value);
console.log(3)
Is this the problem? Node style should have a error and callback?
UserModel.findOne({ 'username_email': value }, (err) => {
console.log(4);
if (err) return res.status(409).send(err);
})
}), async(req, res, next) => {
console.log(5)
try {
let newUser = new UserModel(req.body);
let savedUser = await newUser.save();
console.log(6);
if (savedUser) return res.redirect('/users/registration?success=true');
return next(new Error('Failed to save user for unknown reasons'))
} catch (err) {
return next(err)
}
})
UPDATE
I tried Nick's solution but I get this:
MongoError: E11000 duplicate key error collection: development.users index: email_1 dup key: { : null }
at Function.create (/Users/antoniopavicevac-ortiz/Dropbox/developer_folder/hillfinder/node_modules/mongodb-core/lib/error.js:43:12)
at toError (/Users/antoniopavicevac-ortiz/Dropbox/developer_folder/hillfinder/node_modules/mongodb/lib/utils.js:149:22)
at coll.s.topology.insert (/Users/antoniopavicevac-ortiz/Dropbox/developer_folder/hillfinder/node_modules/mongodb/lib/operations/collection_ops.js:859:39)
at handler (/Users/antoniopavicevac-ortiz/Dropbox/developer_folder/hillfinder/node_modules/mongodb-core/lib/topologies/replset.js:1155:22)
at /Users/antoniopavicevac-ortiz/Dropbox/developer_folder/hillfinder/node_modules/mongodb-core/lib/connection/pool.js:397:18
at process._tickCallback (internal/process/next_tick.js:61:11)
POST /users/registration 500 312.485 ms - 51
^C
Two things I am noticing:
I get back MongoError: E11000 duplicate key error collection: development.users index: email_1 dup key: { : null }
which is the error from having a duplicate email, but number one where is E-mail already in use message in the console from the promise? And two how can I pass the error status "res.status(409).send(err);" from the promise?
The issue was that during your validation, you weren't returning the promise since the mongoose call is async. The rest the code ran before your validator was finished. I commented where you were missing the return.
router.route('/registration')
.get(function(req, res) {
UserModel.find({}, (err, users) => {
if (err) res.status(500).send(err)
res.json(users)
})
})
.post(body('username').custom(value => {
return UserModel.findOne({ 'email': value }).then(user => { // Return Promise
if (user) {
return Promise.reject('E-mail already in use');
}
});
}), async(req, res, next) => {
try {
let newUser = new UserModel(req.body)
let savedUser = await newUser.save(err => {
if (err) return res.json({ success: false, error: err })
return res.json({ success: true })
})
if (savedUser) return res.redirect('/users/registration?success=true');
return next(new Error('Failed to save user for unknown reasons'))
} catch (err) {
return next(err)
}
})
module.exports = router
UPDATE
Just read through express-validator docs. I think you would need to validate the errors during the request process
var router = require('express').Router()
var UserModel = require('../models/UserModel')
var { body, validationResult } = require('express-validator');
router.route('/registration')
.get(function(req, res) {
UserModel.find({}, (err, users) => {
if (err) res.status(500).send(err)
res.json(users)
})
})
.post(body('username').custom(value => {
return UserModel.findOne({ 'email': value }).then(user => { // Return Promise
if (user) {
return Promise.reject('E-mail already in use');
}
});
}), async(req, res, next) => {
// Checks for errors in validation
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(422).json({ errors: errors.array() });
}
try {
let newUser = new UserModel(req.body)
let savedUser = await newUser.save(err => {
if (err) return res.json({ success: false, error: err })
return res.json({ success: true })
})
if (savedUser) return res.redirect('/users/registration?success=true');
return next(new Error('Failed to save user for unknown reasons'))
} catch (err) {
return next(err)
}
})
module.exports = router
I'm creating a demo MEAN app and everything was going well I could Add and Authenticate Users and Add, Delete and Update Messages but after I implemented web token I can only view and delete messages when I try to add a new message I get this error.
The message is still added to my mongodb database but it stops the server.
I was trying to add my code from the components but I'm not allowed as I get a message saying that my post is mostly code and I need to add more information.
zone.js?fad3:2935 POST http://localhost:3000/message?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjp7Il9pZCI6IjVhNWRiMmFjYmVkMWQ3MmZmOGQzMDM3YSIsImZpcnN0TmFtZSI6IkpvaG4iLCJsYXN0TmFtZSI6IkRvZSIsInBhc3N3b3JkIjoiJDJhJDEwJHZmMVQ2S0VCeVZBSE9qSkRyQWg0WC51N3NHYXZZVXNQSHZyOHFNTllydVdJL3lZZXBKR0ZhIiwiZW1haWwiOiJqb2huQGRvZS5jb20iLCJfX3YiOjksIm1lc3NhZ2VzIjpbXX0sImlhdCI6MTUxNjEwMjM1NSwiZXhwIjoxNTE2MTA5NTU1fQ.6Kj1TcprqWRQIAZ9GSDHLxIbf_9DzPhx5qomv6QtxfA net::ERR_CONNECTION_RESET
Message Route
let express = require('express');
let router = express.Router();
let jwt = require('jsonwebtoken');
let User = require('../models/user');
let Message = require('../models/message');
router.get('/', (req, res, next) => {
Message.find()
.populate('user', 'firstName')
.exec( (err, messages) => {
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
res.status(200).json({
message: 'Success',
obj: messages
});
});
});
router.use('/', (req, res, next) => {
jwt.verify(req.query.token, 'secret', (err, decoded) => {
if (err) {
return res.status(401).json({
title: 'Not Authenticated',
error: err
});
}
next();
})
});
router.post('/', (req, res, next) => {
let decoded = jwt.decode(req.query.token);
User.findById(decoded.user._id, (err, user) => {
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
let message = new Message({
content: req.body.content,
user: user
});
message.save((err, result) => {
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
user.messages.push(result);
user.save();
res.status(201).json({
message: 'Saved message',
obj: result
});
});
});
});
router.patch('/:id', (req, res, next) => {
let decoded = jwt.decode(req.query.token);
Message.findById(req.params.id, (err, message) => {
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
if (!message) {
return res.status(500).json({
title: 'No Message Found!',
error: {message: 'Message not found'}
});
}
if (message.user != decoded.user._id) {
return res.status(401).json({
title: 'Not Authenticated',
error: {message: 'Users do not match'}
});
}
message.content = req.body.content;
message.save((err, result) => {
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
res.status(200).json({
message: 'Updated message',
obj: result
});
});
});
});
router.delete('/:id', (req, res, next) => {
let decoded = jwt.decode(req.query.token);
Message.findById(req.params.id, (err, message) => {
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
if (!message) {
return res.status(500).json({
title: 'No Message Found!',
error: {message: 'Message not found'}
});
}
if (message.user != decoded.user._id) {
return res.status(401).json({
title: 'Not Authenticated',
error: {message: 'Users do not match'}
});
}
message.remove((err, result) => {
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
res.status(200).json({
message: 'Deleted message',
obj: result
});
});
});
});
module.exports = router;
Message Service
import { Http, Response, Headers } from "#angular/http";
import { Injectable, EventEmitter } from "#angular/core";
import 'rxjs/Rx';
import { Observable } from "rxjs";
import { Message } from "./message.model";
#Injectable()
export class MessageService {
private messages: Message[] = [];
messageIsEdit = new EventEmitter<Message>();
constructor(private http: Http) {
}
addMessage(message: Message) {
const body = JSON.stringify(message);
const headers = new Headers({'Content-Type': 'application/json'});
const token = localStorage.getItem('token')
? '?token=' + localStorage.getItem('token')
: '';
return this.http.post('http://localhost:3000/message' + token, body, {headers: headers})
.map((response: Response) => {
const result = response.json();
const message = new Message(
result.obj.content,
result.obj.user.firstName,
result.obj._id,
result.obj.user._id);
this.messages.push(message);
return message;
})
.catch((error: Response) => Observable.throw(error.json()));
}
getMessages() {
return this.http.get('http://localhost:3000/message')
.map((response: Response) => {
const messages = response.json().obj;
let transformedMessages: Message[] = [];
for (let message of messages) {
transformedMessages.push(new Message(
message.content,
message.user.firstName,
message._id,
message.user._id)
);
}
this.messages = transformedMessages;
return transformedMessages;
})
.catch((error: Response) => Observable.throw(error.json()));
}
editMessage(message: Message) {
this.messageIsEdit.emit(message);
}
updateMessage(message: Message) {
const body = JSON.stringify(message);
const headers = new Headers({'Content-Type': 'application/json'});
const token = localStorage.getItem('token')
? '?token=' + localStorage.getItem('token')
: '';
return this.http.patch('http://localhost:3000/message/' + message.messageId + token, body, {headers: headers})
.map((response: Response) => response.json())
.catch((error: Response) => Observable.throw(error.json()));
}
deleteMessage(message: Message) {
this.messages.splice(this.messages.indexOf(message), 1);
const token = localStorage.getItem('token')
? '?token=' + localStorage.getItem('token')
: '';
return this.http.delete('http://localhost:3000/message/' + message.messageId + token)
.map((response: Response) => response.json())
.catch((error: Response) => Observable.throw(error.json()));
}
}