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 errorawait 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 properlyconsole.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}))