Reputation: 97
Consider the following (pseudo)function to update a database:
function my_function(req, res, input) {
try {
// This sanitizeInput() function throws error message if input is invalid
sanitizeInput(input);
catch (err) {
res.status(500).json({id:"sql_error",message:err});
return;
}
dbCreateRowPromise(input)
.then(result => {//Handle success})
.catch(err => {res.status(500).json({id:"sql_error",message:err}})
}
As you can see I'm writting catch twice and both times I'm writing the same response 500 status and handling the catch in the same way. Is there any good way to combine this 2 catches in a single one?
Upvotes: 0
Views: 70
Reputation: 877
You should consider making sanitizeInput return a promise. Then you can write:
sanitizeInput(input)
.then(function(data)){
return dbCreateRowPromise(input);
})
.then(function(data)){
//success
})
.catch(function(error)){
//all failures
})
I am assuming your functions return something - if not data
would just be null
Upvotes: 1
Reputation: 665364
The easiest way is to use async
/await
syntax for your function:
async function my_function(req, res, input) {
try {
input = sanitizeInput(input);
let result = await dbCreateRowPromise(input);
// handle result
} catch (err) {
res.status(500).json({id:"sql_error",message:err});
}
}
Alternatively, make a promise for sanitizeInput
so that you can use promise chaining and handle errors from it as a rejection.
var promise;
try {
promise = Promise.resolve(sanitizeInput(input));
} catch (err) {
promise = Promise.reject(err);
}
promise.then(input =>
dbCreateRowPromise(input)
).then(result => {
// Handle success
}).catch(err => {
res.status(500).json({id:"sql_error",message:err});
});
or
new Promise(resolve =>
resolve(sanitizeInput(input))
).then(input =>
dbCreateRowPromise(input)
).then(…).catch(…);
or
Promise.resolve(input).then(sanitizeInput).then(dbCreateRowPromise).then(…).catch(…)
Upvotes: 0
Reputation: 13685
It seems like what you're encountering is a mixture of synchronous code, promises and async callbacks which have different error handling techniques.
One solution is to just do what you're doing, handle the different styles of errors individually, but this could get confusing and complicated. The other is to attempt to unify all such code into a single style, using simple abstractions to smooth them over.
I would personally attempt to normalize all of my calls as async callback style calls and then unify the error handling this way. For example it looks like you're using express
middleware here, so I would pass all errors out and handle them in an error handler middleware.
import { auto, constant } from 'async'
const { assign } from Object
function sanitize (opts, callback) {
const { input } = opts
try {
sanitizeInput(input)
callback()
} catch (err) {
callback(assign(err, { status: 'sanitize_error', statusCode: 500 })
}
}
function createRow (opts, callback) {
const { santizie: input } = opts
dbCreateRowPromise(input)
.then(result => callback(null, result))
.catch(err => callback(assign(err, { status: 'create_row_error', statusCode: 500 }))
}
function my_function(req, res, input, next) {
const block = {
input: constant(input),
sanitize: ['input', sanitize],
createRow: ['sanitize', createRow]
}
auto(block, (err, result) => {
if (err) return next(err)
res.status(200).json({ status: 'ok' }))
})
}
function errorHandler(err, req, res) {
res.status(err.statusCode).json(err)
}
Upvotes: 1
Reputation: 12806
Note that in your current way of writing the code, you are not returning anything, and any following statements will assume that everything went ok, as you are handling the catch
already, and transform the response.
I think you could just rewrite your statement in the following way:
function sanitizeInput( input ) {
if (input % 2 === 0) {
throw 'Cannot input even number';
}
return input;
}
function dbCreateRowPromise( input ) {
return Promise.resolve(input);
}
function my_function( input ) {
return Promise.resolve(input)
.then( sanitizeInput )
.then( dbCreateRowPromise );
}
// perfectly normall input
my_function(5)
.then( out => console.log(out))
.catch( err => console.log('error occured', err));
// errourness input
my_function(4)
.then( out => console.log(out))
.catch( err => console.log('error occured', err));
Just use the promises to build a chain of events, and let the error be thrown. In case it is not handled by the callee, the error will be shown in the console eventually.
Upvotes: 1