Basically, the question is do I need to use next(err) when encountering any errors? The nodejs error documentation says it is fine to use a standard sort of if(err) else... for asynchronous callbacks and EventEmitters, as long as the error isnt handled with a try-catch block for non async-await functions, as it will cause crashing. If I do need to use them, what is to prevent the next() function being called multiple times in the same handler for different asynchronous operations? Wouldnt using the default error handler cause headers to be sent multiple times and cause an error of its own when using event emitters ?
Apologies if the question has been asked, its just I cannot find a specific answer to why usage of express.js error handling is preferred.
If you are asking if you need to use an explicit next(err) in a handler,
e.g.
app.get('/someurl', (req, res, next) => {
//do something - whoops had an error
next(err);
})
No, the above is not required in a handler.
The only time you would need to explicitly wrap or pass on the error is if you have, for example, used a try/catch and are not handling the error condition itself in the handler, i.e. not returning a response in the handler (Not sure why you would want to do that).
What will happen above when an error occurs in the handler, express will continue on through the middlewares until it finds a handler that will deal with your error.
If there are none, it will exit.
So to use a global error handler, you could write your app like the following and not worry about next(err) in each handler function.
app.get('/route/one', async (req, res) => {
// do something that could throw an error
const result = await aFunctionThatCouldThrowAnError();
// No error handling in this function
res.json({ result });
});
app.get('/route/two', (req, res) => {
res.json({ hello: 'world-two' });
});
// A Global Error handler
app.use((err, req, res, next) => {
//handle all errors here
if(err) {
res.status(500).send('some error message')
}
res.status(404).send('not found');
});
Note that the order of middlewares is important, so the global error handler should be applied last.
Related
Below is the piece of code for my route.patch function that I defined for /:productId
route.patch('/:productId',(req,res,next)=>{
const id = req.params.productId;
const updateOps = {};
console.log(req.body);
for (const ops of req.body) {
updateOps[ops.propName] = ops.value;
console.log(updateOps);
}
res.status(200).json({Message: 'Hi'});
});
console.log(req.body) before the for loop is working but the console.log(updateOps) inside for loop is not working. And the even the res.status(200).json({Message: 'Hi'}); is not working . I am getting a route not found error.
Basically everything before for loop is working and everything after for loop is not working.
Can you please let me know where am I doing wrong. Is it the way I use for loop inside route.patch is wrong? Any help is highly appreciated.
Thanks
Answering your question regarding the error-handling from the comments. You have the following middlewares:
app.use((req, res, next) => {
const error = new Error('Not found');
//console.log(error.status) //console.log(error.message)
error.status = 404; //console.log(error.message)
next(error);
});
app.use((error, req, res, next) => {
res.status(error.status || 500);
res.json({
error: {
message: 'Route not found'
}
})
});
So for every request an error-object will be created which you assign status 404 and pass it on to the next middleware. There you send the error response and since the status is already set to 404 this status is used.
Actually you should just remove the first middleware where you create the error, as this would be done for every request. Express already handles requests to routes that do not exist and will return a 404 not found response. You can keep the second middleware to handle any other unhandled errors though (you should change the error message though :))
I am running redux on node. To handle asynchronous actions, like reading a file or listing of a directory, I am using redux-thunk in combination with Promises. So a typical action can look like that:
const
fs = require('fs'),
{ promisify } = require('util'),
readdir = promisify(fs.readdir);
const listFiles = dir => dispatch =>
readdir(dir)
.then(files => dispatch({
type: '…',
payload: { files }
}));
So:
try {
store.dispatch(listFiles('/some/path'));
catch (error) {
//some rescue plan here,
//won't work if directory not exists
}
wont work here, because the action is asynchronous and right now, the only way I see to handle all errors is to add a .catch() to all promises in all actions and dispatch an error action there.
That has two downsides:
a lot of code repetition and
i need to know all possible errors in ahead.
So my question is: Is there any way to create a global error handler, which will also be called if an asynchronous action fails, such that I can add some error indicating information to the state, which can be displayed?
Could that be possible with a »storeEnhancer« or some »middleware«?
UPDATE
I could find something that is really helpful:
process.on('unhandledRejection', (reason, promise) => {
console.log(reason.message);
});
That callback is triggered whenever a Promise is rejected and no catch block is added. Right now that seams to do the trick, but anyway, I would prefer a solution that basically does the exact same thing, but only for rejected Promises which are triggered within store.dispatch(), so only when an error within the processing of actions/middleware/reducers within redux comes to happen.
If you're looking for a redux middleware solution, take a look at redux-catch.
I'm building an Express API Server with Mongoose,
with Express i'm catching all errors and response with the error message
app.use(function (err, req, res, next) {
res.status(404).json({message: err.message})
})
But with Mongoose, i should pass each Error manually to next() each time when i do a query.
Is there any way that make mongoose throw the error to next() automatically so that i could never concern about the error handling of a query anymore?
Here is the background of the question : I'm following the kick-off-koa using Koa 2. But the exercises in the kick-off are designed for Koa 1. I've created an issue for this problem of Koa 2 : Task of error handler with Koa 2 cannot pass.
For short, my problem is how to display a custom error page when a 500 error happens.
Here are the codes :
// error handler middleware
function errorHandler(ctx, next) {
try {
return next();
}
catch(err) {
ctx.status = err.status || 500;
// I would like to display the custom message as follows
ctx.body = 'Oops! internal server error';
// with emitting the error event, don't work
// ctx.app.emit('error', err, ctx);
}
}
// to generate error
app.use(router.get('/error', ctx => {
ctx.throw('oops', 500);
}));
But my page of error is always displaying as "Internal Server Error", which is the default message. It seems that ctx.body = 'Oops! internal server error'; couldn't modify the page.
Thanks for the helps!
If you are using Koa2, you don't have to return inside middleware, instead, use await. And by the way, your middleware function MUST be an async function.
Here is an example of a combined 404 and 500 middleware:
app.use(async (ctx, next) => {
try {
await next()
if (ctx.status === 404) ctx.throw(404)
} catch (err) {
console.error(err)
ctx.status = err.status || 500
ctx.body = errorPage.render({ // Use your render method
error: err,
})
}
})
// Your normal routes here
First, Koa awaits for the next middleware in the chain (which is your normal routes). If nothing is found or an error occurred, the middleware chain goes backwards and the next line is executed, which throws a 404 and its captured inside the catch.
Now in the catch statement, you can get either 404, 500 (by default) or 5xx if other error occurred.
The body of the page is also set with a render of your template and passing the error to the template so you can make use of it.
You don't have to emit the error as this is the last catch in the chain.
How can I implement a custom error handler in Express using CSRF middleware after users click the back button in browser and resubmit the form? By default Express return a 403 page with lots of stack traces. I want to replace it by for example redirecting user to a custom error page. How can I do that?
Here are some examples of writing custom error handlers in Express: https://github.com/visionmedia/express/blob/master/examples/error-pages/index.js
Here are the custom error handlers I use: Error handling in an Express route
You might also want to consider modifying connect to return a different code than 403 when CSRF fails. You can change it here: https://github.com/senchalabs/connect/blob/master/lib/middleware/csrf.js#L82
You might choose 428 Precondition Required. The full list is here: http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
That way, you could have a special message shown only for CSRF failures.
Like any other well designed middleware csurf passes the error to next. So it's possible to react on the raised error in the following way:
var csurf = require('csurf')();
app.use(function (req, res, next) {
csurf(req, res, function (err) {
if (err) {
// do what ever with err
} else {
next();
}
});
});