How to check function error using if/else statement? - javascript

I am creating session and sending traps to snmp devices, my code is working as expected and sending trap messages to host, Now below i have added validation to check if session has error while establishing connection, then throw error dont send trap message. So my question here is how can we execute function while checking if/esle condition and see if error exist in validateSession if error exist close session else send trap.
main.js
var session = snmp.createSession(host,"public",sessionOptions);
try {
function validateSession(){
session.on ("error", function (error) {
console.log (error);
session.close ();
});
};
if(!validateSession(){
session.trap(trapOid, varbinds, options, function (error) {
if (error)
console.log(error);
else
console.log('SNMP successfully delivered');
});
})
} catch (e) {
console.log("SNMP processing error: " + e);
}

Related

Is my code the best way to use async await?

Am try to implement and learn async await functions in my login example, but I don't know if is the best, elegant and clean code. I have doubs meanly in catch errors, and if I need implement in a best way the const and functional programing. Can share your opinions?
app.post('/', async (req, res) => {
try {
const { email } = req.body.email; // destructuring
const usuarioEncontrado = await Usuario.findOne({email: email});
// Validate user exist
if (!usuarioEncontrado) { // when not exist return null
throw res.status(404).json({error: 'El usuario no existe'});
}
// validate user pass
if (!bcrypt.compareSync(req.body.password, usuarioEncontrado.password)) {
throw res.status(404).json({error: 'No match'});
}
const token = jwt.sign( // generate token
{
usuario: usuarioEncontrado
},
SEED,
{
expiresIn: (60 * 60)
}
);
res.status(200).json({ // send response
token: token,
usuario: usuarioEncontrado
});
} catch (e) { // send error
res.status(404).json(e);
}
}
THANKS
Your code shows a couple problems:
You're attempting to send double responses. First you do throw res.status(404).json(...). Then, you catch that exception and do res.status(404).json(e) again. That's not right. If you're going to send the response, then just return, don't throw. Or, just throw the exception without sending a response and send the actual error response from the catch handler.
Also, throw res.status(404).json({error: 'No match'}); sends the response and then throws whatever .json() returns which is probably not what you want. That won't be an error object of any kind.
I prefer to centralize the places I send an error response to one place in the request handler. That keeps you from ever attempting to send multiple responses and just makes the flow of the request handler easier to understand (in my opinion).
To do that, I just throw a custom error that may have a custom message/status associated with it and then catch all possible errors in one place. Here's one way to do that. The myError class can be used everywhere in your project, not specific to just one route. The idea is that often when you throw, you know in that context what you want the status and message to be so you set that in the custom Error object and can then use that info in the catch. The catch then has to determine whether it has your custom error or just a regular error. First, I have a reusable Error subclass that lets me throw, not only a message, but also a status value.
// reusable error class that contains a status in addition to the message
class MyError extends Error {
// this static method saves having to compare if it's a custom error object or not
// every time we use this
static sendError(res, e, status = 500) {
if (e instanceof MyError) {
e.sendError(res);
} else {
res.sendStatus(status);
}
}
constructor(msg, status = 500) {
// allow calling with or without new
if (!(this instanceof MyError)) {
return new MyError(msg, status);
}
super(msg);
this.status = status;
}
sendError(res) {
res.status(this.status).send(this.message);
}
}
And, then here's how you use that in your code and centralize the sending of the error status.
app.post('/', async (req, res) => {
try {
const { email } = req.body.email; // destructuring
const usuarioEncontrado = await Usuario.findOne({email: email});
// Validate user exist
if (!usuarioEncontrado) { // when not exist return null
throw MyError('El usuario no existe', 404);
}
// validate user pass
if (!bcrypt.compareSync(req.body.password, usuarioEncontrado.password)) {
throw MyError('No Match', 404);
}
const token = jwt.sign( // generate token
{
usuario: usuarioEncontrado
},
SEED,
{
expiresIn: (60 * 60)
}
);
res.status(200).json({ // send response
token: token,
usuario: usuarioEncontrado
});
} catch (e) { // log and send error response
// e may be either MyError or some other system generated Error
console.log(e);
MyError.sendError(res, e);
}
}

Javascript syntax errors swallowed and hidden in async/await functions

I'm learning Electron.js and I want to use async/await feature in my code but I'm a bit disappointed because syntax errors are swallowed and silent which make my future projects a nightmare for debugging.
db module:
exports.connect = function(){
return new Promise( (resolve, reject) => {
connection = mysql.createConnection({
host : host,
port : port,
user : user,
password : null, // or the original password : 'apaswword'
database : database
});
query = util.promisify(connection.query).bind(connection);
connection.connect(function(error) {
// in case of error
if(error){
reject(error);
}
resolve(true);
});
connection.on('error', error => {
dispatcher.send('connection-error', error.code);
});
});
}
bootstrap module:
async function connectDB(){
try{
let connected = await db.connect(THIS_SHOULD_THROW_ERROR);
return connected;
}catch( error ){
dispatcher.send('connection-error', error);
}
}
exports.init = async function( win ){
dispatcher.init(win);
try{
const connected = await connectDB();
/*if(!connected){
dispatcher.send('fatal-error', "MYSQL NOT CONNECTED");
}*/
}catch( error ){
dispatcher.send('fatal-error', error);
}
}
This code is trying to connect to mysql and send error if it can't connect, but notice the syntax error "THIS_SHOULD_THROW_ERROR" that should halt execution or throw error, but it doesn't and my code has no errors at all even if it can't connect to mysql.
Notice that if I remove syntax error my code works well and catches mysql connection error.
I've read everywhere that is normal behavior of javascript async/promises code, but I'd like to know if there is a solution to catch syntax errors to make my debuging easier. Thank you
If you have a syntax error inside a try/catch block or you are using a catch all mechanism (i.e. process.on('uncaughtException'...) the syntax error would be swallowed:
/* content of test.js */
console.log('hello')
THIS_SHOULD_THROW_ERROR // comment this line and run again
try {
THIS_SHOULD_THROW_ERROR_BUT_DOESNOT
} catch (err) {
// using err will throw exception: console.log(err)
console.log('error happened')
}
Now run the script with and without comment in the line specified:
$ node test.js
So you are doing such somewhere in your code.
PS:
async function connectDB(){
try{
let connected = await db.connect(THIS_SHOULD_THROW_ERROR);
return connected;
}catch( error ){
dispatcher.send('connection-error', error);
// throw error
}
}
The db.connect(THIS_SHOULD_THROW_ERROR) is in try block while you don't throw the error. If dispatcher.send doesn't throw the error in some point that error is swallowed.
Thanks to Xarqron & Bergi I made it finnaly work, I just had to throw error in both connectDB and init catch's
async function connectDB(){
try{
let connected = await db.connect(THIS_SHOULD_THROW_ERROR);
return connected;
}catch( error ){
dispatcher.send('connection-error', error);
throw error;
}
}
exports.init = async function( win ){
dispatcher.init(win);
try{
const connected = await connectDB();
/*if(!connected){
dispatcher.send('fatal-error', "MYSQL NOT CONNECTED");
}*/
}catch( error ){
dispatcher.send('fatal-error', error);
throw error;
}
}
Do you advice to always throw error in every catch block so that debugging would be easier ? Because I had hard time to find this kind of bug without any console warning or error

What's the best way to deal with an error in the server side and in the client side using nodejs + express

I'd like to know the best way to deal with errors in a response - request.
I have this route that receive a request:
app.get('/getInfo', function (req, res, next) {
let obj = {}
try {
obj = {
...
date: lastUpdatedDate('./utils/appVersion.js'),
...
}
res.status(200).send(obj)
} catch (error) {
console.log(error.message)
res.send({error: "The data wasn't load"})
}
})
And this function where the request is made
getInfo () {
axios.get(process.env.REACT_APP_HOST + '/getInfo')
.then(resp => {
this.appInfoHandler(resp.data)
})
.catch(function (error) {
console.log(error)
})
}
What's the best way to deal with the error if it occurs in the server side?
Let's supose that in this code block the directory doesn't exists: lastUpdatedDate('./directoreyDoesntExists/appVersion.js'),
So my code goes to the catch block.
Should I send the error like this:
res.send({error: "The data wasn't load"})
Should I set a status like this?
res.status(500).send({error: "The data wasn't load"})
Or should I set a status with a different status code?
Based on that, what's the best way to deal with it in my frontend method getInfo() to get the error and show the error message on web interface?
Should I do an if else inside the .then block like this?
getInfo () {
axios.get(process.env.REACT_APP_HOST + '/getInfo')
.then(resp => {
if(resp.status === 200){
this.appInfoHandler(resp.data)
}else if (resp.status === 400){
//print error message on web interface
}else if (resp.status === 500){
//print error message on web interface
})
.catch(function (error) {
console.log(error)
})
Or should I deal with this error directly in the catch block like this
getInfo () {
axios.get(process.env.REACT_APP_HOST + '/getInfo')
.then(resp => {
this.appInfoHandler(resp.data)
})
.catch(function (error) {
//print error message on web interface
})
}
For this case
res.send({error: "The data wasn't load"})
vs
res.status(500).send({error: "The data wasn't load"})
send a status is just more detailed, but both are ok.
check Proper way to set response status and JSON content
For this case, depends on what you need
then(resp => {
if(resp.status === 200){
this.appInfoHandler(resp.data)
}else if (resp.status === 400){
//print error message on web interface
}else if (resp.status === 500){
//print error message on web interface
})
.catch(function (error) {
console.log(error)
})
vs
getInfo () {
axios.get(process.env.REACT_APP_HOST + '/getInfo')
.then(resp => {
this.appInfoHandler(resp.data)
})
.catch(function (error) {
//print error message on web interface
})
}
You can handle all the errors sending them to the catch block
else if (resp.status === 400){
//print error message on web interface
not printing the error in here but throwing a new error that will be send it to the catch block
throw new ApiError("UserNotFount",400,"not found");
throw new Error('Error 400, not found');
For this case
res.send({error: "The data wasn't load"})
vs
res.status(500).send({error: "The data wasn't load"})
I would suggest sending error as well as status code because that will be more descriptive for the client.
and for the second case
getInfo () {
axios.get(process.env.REACT_APP_HOST + '/getInfo')
.then(resp => {
if(resp.status === 200){
this.appInfoHandler(resp.data)
}else if (resp.status === 400){
//print error message on web interface
}else if (resp.status === 500){
//print error message on web interface
})
.catch(function (error) {
console.log(error)
})
vs
getInfo () {
axios.get(process.env.REACT_APP_HOST + '/getInfo')
.then(resp => {
this.appInfoHandler(resp.data)
})
.catch(function (error) {
//print error message on web interface
})
}
In this case I would suggest to use the catch block directly whenever you get an error because response status depends on error but not the other way around
As a beginner working on a REST Api, you should take a look at a guidelines - microsoft's are pretty legit: https://learn.microsoft.com/en-us/azure/architecture/best-practices/api-design.
Basically, you need to return the correct HTTP code for each request, take a look at https://http.cat/ - for example if the request is malformed, return 400, and if the user is unauthorized return 401:
if (!req.body.name) {
res.status(400).send({ error: 'missing user name' }); // 400 bad request
}
const user = getUser(req.body.name, req.body.pass);
if(!user) {
res.status(401).send({ error: 'user does not exist' }); // 401 unauthorized
}
try {
const token = createToken(user);
// better to set a cookie
res.status(200).send({ token }); // 200 success
} catch(e) {
res.status(500).send({ erroe: e.message }); // 500 internal error
}
if(isTeapot) {
res.status(418).send({ error: 'I can only make tea' }); // 418 teapot, totally real
}
To make things easier there are a lot of libraries to help you generate better error messages and handle errors better, one of my favorites is celebrate
Any status code other that 200 would mean unsuccessful so you dont need to use those if-else statements. The better alternative is to catch the error and send it with response as it is. The benefit is that you would receive the type of error occured without hardcoding the status codes.
(for ex, we take the status code here to be 400 unsuccessful)
.catch(function (error) {
//print error message on web interface
res.status(400).send(JSON.stringify(error, undefined, 2));
});
By using the stringify method you can print the exact error on the console also.
.catch(function (error) {
console.log(JSON.stringify(error, undefined, 2));
});
The parameters in the stringify method here are:
error object
undefined: The array which contains the keys for filtering the keys in the object(here, error). All those keys present in this array are only the ones not filtered out.
2: It is used to introduce whitespace in object representation

Angular 5 HttpClient Error response not catchable

We're working with Angular 5 and a Spring 2 OAuth Backend.
Now when I send an old token it's of course expired. It returns status code: 401 and an error response with invalid token and so on. Now I can't see it in my logs or when I catch the error. I want to get the error so I can at first log it and later on either refresh the token or send him to the Login Page.
Now if i subscribe to the request with:
.subscribe(res => {
//just random stuff.
}, err => {
console.log("error", err);
});
I just see this response in the log with an unknown error like in this image
Could it be failure of the backend? Because i also see in the logs something like a "No 'Access-Control-Allow-Origin' header is present"-error, although it's because of the invalid token.
Although I can see this response code in Google Chrome Dev Tools
and a 401 status code.
So I tried to find a solution myself. I've already got an interceptor and tried it with some solutions
return next.handle(authReq)
.catch(error => {
console.log("im in here");
console.log(error);
return Observable.throw(error);
});
The Http Service just throws an error that catch is not a function without even logging the error or the "im in here".
I have also tried with the .do after next.handle and I got the same error like catch
.do((event: HttpEvent<any>) => {
if (event instanceof HttpResponse) {
// do stuff with response if you want
}
}, (err: any) => {
console.log(err);
if (err instanceof HttpErrorResponse) {
if (err.status === 401) {
}
}
});
I've tried with pipe after the http.get but it doesn't work either.
http.get(...).pipe(
retry(3), // retry a failed request up to 3 times
catchError(this.handleError) // then handle the error
);
import 'rxjs/add/operator/catch';
Somefunc(){
this.httpClient
.get("data-url")
.subscribe(
data => console.log('success', data),
error => console.log('oops', error)
);
}
OR
this.httpClient
.get("data-url")
.catch((err: HttpErrorResponse) => {
// simple logging, but you can do a lot more, see below
console.error('An error occurred:', err.error);
});
Should work.

How to handle error in Angular Controller from MongoDB database update/delete in Express?

I am trying to figure out how to handle an error when deleting or updating a document in MongoDB in Angular JS?
I have the following route in Node/Express:
function handleError(res, reason, message, code) {
console.log("ERROR: " + reason);
//log the reason for the error
res.status(code || 500).json({
"error": message
});
}
app.delete("/polls/:id", auth, function(req, res) {
db.collection(POLLS_COLLECTION).deleteOne({
_id: new ObjectID(req.params.id), userID: req.user.id
//userID must match the req.user.id from Passport to make sure the poll belongs to the user
}, function(err, doc) {
if (err) {
handleError(res, err.message, "Failed to delete poll");
} else {
res.status(204).end();
}
});
});
The following in an Angular JS controller:
$scope.deleteThisPoll = function(){
Polls.deletePoll($routeParams.pollId)
.then(function(response){
alert("Poll deleted!");
var url = "/mypolls/" + $scope.userID;
$location.path(url);
}, function(response){
alert("Error deleting poll");
console.log(response);
})
};
deleteThisPoll in the controller calls a deletePoll service that sends a a request to the route:
this.deletePoll = function(pollId){
var url = "/polls/" + pollId;
return $http.delete(url);
};
What I want is to alert "Error deleting poll" from the Angular controller when the database delete is not executed (because for example user is not authenticated or the poll doesnt belong to the user) and "Poll Deleted" when the delete was successfull.
However: the error callback is never used and the app always alerts "Poll deleted!" no matter if the document was deleted or not deleted.
Doesn't my route send an error response when the delete was not executed and will it not hit my Angular error callback?
You can do like code below
Put this HTML code where you want to show error message :
<div style="color:red;">
{{error}}
</div>
In your angular js controller :
$scope.deleteThisPoll = function(){
Polls.deletePoll($routeParams.pollId)
.then(function(response){
alert("Poll deleted!");
var url = "/mypolls/" + $scope.userID;
$location.path(url);
}, function(response){
$scope.error="Any error message you like to show";
console.log(response);
})
};
If your API return an error. you can catch it like this :
Polls.deletePoll($routeParams.pollId).then(function(response) {
//SUCCESS CODE
}).catch(function(error) {
//NOTIFY ERROR
//NotifyService.display(error);
console.log(error);
});
thanks guys. I found out that MongoDB for some reason always returns a result object even when there was no delete/update. I solved this by checking for the result.deletedCount propety that is set to 1 or 0. Like so:
if(err){
res.status(500).end();
}
if(result.deletedCount === 0){
res.status(404).end();
//error handling in Angular error callback
} else {
res.status(204).end();
//error handling in Angular success callback
}
});
});
this makes sure that not always a 204 is send whether or not the delete was successfull.

Categories

Resources