Background
If you are a Js developer, you probably have used async
and await
, and you love them.
No more callback hell or .then
chains. Just like writing a synchronous program.
Util you run into UnhandledPromiseRejectionWarning
or Uncaught (in promise) Error
You begin to wrap every piece of code using try.. catch..
, but that seems a lot of work.
But I've got good news, you can write a custom async function error handler:
Solution
const asyncHandler = fn => async (...args) => {
try {
await fn(...args);
} catch (err) {
console.log(err);
}
};
It takes all types of functions with any number of arguments.
use it like this:
const asyncHandler = fn => async (...args) => {
try {
await fn(...args);
} catch (err) {
console.log(err);
}
};
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
const yourFunction = async () => {
await sleep(2000);
throw 'something wrong';
return 'success';
}
(async ()=> {
await yourFunction(); // will cause Uncaught error
await asyncHandler(yourFunction)(); // will handle the error properly
})();
Return values
Of course when you need the result of the async function, you can:
const asyncHandler = fn => async (...args) => {
try {
return await fn(...args);
} catch (err) {
console.log(err);
}
};
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
const yourFunction = async () => {
await sleep(2000);
// throw 'something wrong';
return 'success';
}
(async ()=> {
const result = await asyncHandler(yourFunction)(); //will handle the error properly
console.log(result); // => 'success'
})();
Custom error handling
if you need some custom error handling, for example, to use it in express.js
you can do simply by adding some of your custom logic
const asyncHandler = fn => async (...args) => {
try {
await fn(...args);
} catch (err) {
logger.error(err);
const resFn = args.find(arg => arg.name === 'res');
if (resFn) {
let errors = {
message: 'Internal Sever Error',
error: err
};
if (err instanceof mongoose.Error.ValidationError) {
errors = {
message: 'Mongoose Model Validation Error',
error: err
};
}
if (err instanceof mongoose.mongo.MongoError) {
errors = {
message: 'MongDB Error',
error: err
};
}
resFn.status(500).json(errors);
}
}
};
later you use it in express routers like this:
router.get('/item',
asyncHandler(async (req, res) => {
// router logic here
})
)
Top comments (2)
Can I pass a custom error object to the asyncHandler from with the '/item' route
Sure, you can throw custom error, and handle it in asyncHandler, just make sure you have a way to identify it.